Sebastian Stenzel 9 years ago
parent
commit
c306151980

+ 2 - 1
main/ui/src/main/java/org/cryptomator/ui/CryptomatorModule.java

@@ -90,7 +90,8 @@ class CryptomatorModule {
 
 
 	@Provides
 	@Provides
 	@Singleton
 	@Singleton
-	FrontendFactory provideFrontendFactory(WebDavServer webDavServer) {
+	FrontendFactory provideFrontendFactory(WebDavServer webDavServer, Settings settings) {
+		webDavServer.setPort(settings.getPort());
 		webDavServer.start();
 		webDavServer.start();
 		return closeLater(webDavServer, WebDavServer::stop);
 		return closeLater(webDavServer, WebDavServer::stop);
 	}
 	}

+ 41 - 8
main/ui/src/main/java/org/cryptomator/ui/controllers/SettingsController.java

@@ -14,31 +14,39 @@ import java.util.ResourceBundle;
 import javax.inject.Inject;
 import javax.inject.Inject;
 import javax.inject.Singleton;
 import javax.inject.Singleton;
 
 
+import org.apache.commons.lang3.CharUtils;
 import org.cryptomator.ui.settings.Settings;
 import org.cryptomator.ui.settings.Settings;
 import org.fxmisc.easybind.EasyBind;
 import org.fxmisc.easybind.EasyBind;
 
 
-import javafx.application.Application;
 import javafx.fxml.FXML;
 import javafx.fxml.FXML;
 import javafx.scene.control.CheckBox;
 import javafx.scene.control.CheckBox;
+import javafx.scene.control.TextField;
+import javafx.scene.input.KeyEvent;
 
 
 @Singleton
 @Singleton
 public class SettingsController extends AbstractFXMLViewController {
 public class SettingsController extends AbstractFXMLViewController {
 
 
-	private final Application app;
 	private final Settings settings;
 	private final Settings settings;
 
 
 	@Inject
 	@Inject
-	public SettingsController(Application app, Settings settings) {
-		this.app = app;
+	public SettingsController(Settings settings) {
 		this.settings = settings;
 		this.settings = settings;
 	}
 	}
 
 
 	@FXML
 	@FXML
 	private CheckBox checkForUpdatesCheckbox;
 	private CheckBox checkForUpdatesCheckbox;
 
 
+	@FXML
+	private TextField portField;
+
 	@Override
 	@Override
 	public void initialize() {
 	public void initialize() {
-		checkForUpdatesCheckbox.setSelected(settings.isCheckForUpdatesEnabled());
+		checkForUpdatesCheckbox.setDisable(areUpdatesManagedExternally());
+		checkForUpdatesCheckbox.setSelected(settings.isCheckForUpdatesEnabled() && !areUpdatesManagedExternally());
+		portField.setText(String.valueOf(settings.getPort()));
+		portField.addEventFilter(KeyEvent.KEY_TYPED, this::filterNumericKeyEvents);
+
+		EasyBind.subscribe(portField.textProperty(), this::portDidChange);
 		EasyBind.subscribe(checkForUpdatesCheckbox.selectedProperty(), settings::setCheckForUpdatesEnabled);
 		EasyBind.subscribe(checkForUpdatesCheckbox.selectedProperty(), settings::setCheckForUpdatesEnabled);
 	}
 	}
 
 
@@ -52,8 +60,33 @@ public class SettingsController extends AbstractFXMLViewController {
 		return ResourceBundle.getBundle("localization");
 		return ResourceBundle.getBundle("localization");
 	}
 	}
 
 
-	// private boolean areUpdatesManagedExternally() {
-	// return Boolean.parseBoolean(System.getProperty("cryptomator.updatesManagedExternally", "false"));
-	// }
+	private void portDidChange(String newValue) {
+		try {
+			int port = Integer.parseInt(newValue);
+			if (port < Settings.MIN_PORT) {
+				settings.setPort(Settings.DEFAULT_PORT);
+			} else if (port < Settings.MAX_PORT) {
+				settings.setPort(port);
+			} else {
+				portField.setText(String.valueOf(Settings.MAX_PORT));
+			}
+		} catch (NumberFormatException e) {
+			portField.setText(String.valueOf(Settings.DEFAULT_PORT));
+		}
+	}
+
+	private void filterNumericKeyEvents(KeyEvent t) {
+		if (t.getCharacter() == null || t.getCharacter().length() == 0) {
+			return;
+		}
+		char c = CharUtils.toChar(t.getCharacter());
+		if (!(CharUtils.isAsciiNumeric(c) || c == '_')) {
+			t.consume();
+		}
+	}
+
+	private boolean areUpdatesManagedExternally() {
+		return Boolean.parseBoolean(System.getProperty("cryptomator.updatesManagedExternally", "false"));
+	}
 
 
 }
 }

+ 7 - 3
main/ui/src/main/java/org/cryptomator/ui/controllers/UnlockController.java

@@ -21,6 +21,7 @@ import org.cryptomator.crypto.engine.InvalidPassphraseException;
 import org.cryptomator.crypto.engine.UnsupportedVaultFormatException;
 import org.cryptomator.crypto.engine.UnsupportedVaultFormatException;
 import org.cryptomator.frontend.CommandFailedException;
 import org.cryptomator.frontend.CommandFailedException;
 import org.cryptomator.frontend.FrontendCreationFailedException;
 import org.cryptomator.frontend.FrontendCreationFailedException;
+import org.cryptomator.frontend.FrontendFactory;
 import org.cryptomator.frontend.webdav.mount.WindowsDriveLetters;
 import org.cryptomator.frontend.webdav.mount.WindowsDriveLetters;
 import org.cryptomator.ui.controls.SecPasswordField;
 import org.cryptomator.ui.controls.SecPasswordField;
 import org.cryptomator.ui.model.Vault;
 import org.cryptomator.ui.model.Vault;
@@ -28,6 +29,7 @@ import org.fxmisc.easybind.EasyBind;
 import org.slf4j.Logger;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.slf4j.LoggerFactory;
 
 
+import dagger.Lazy;
 import javafx.application.Application;
 import javafx.application.Application;
 import javafx.application.Platform;
 import javafx.application.Platform;
 import javafx.beans.property.ObjectProperty;
 import javafx.beans.property.ObjectProperty;
@@ -51,16 +53,18 @@ public class UnlockController extends AbstractFXMLViewController {
 
 
 	private static final Logger LOG = LoggerFactory.getLogger(UnlockController.class);
 	private static final Logger LOG = LoggerFactory.getLogger(UnlockController.class);
 
 
-	private final ExecutorService exec;
 	private final Application app;
 	private final Application app;
+	private final ExecutorService exec;
+	private final Lazy<FrontendFactory> frontendFactory;
 	private final WindowsDriveLetters driveLetters;
 	private final WindowsDriveLetters driveLetters;
 	private final ChangeListener<Character> driveLetterChangeListener = this::winDriveLetterDidChange;
 	private final ChangeListener<Character> driveLetterChangeListener = this::winDriveLetterDidChange;
 	final ObjectProperty<Vault> vault = new SimpleObjectProperty<>();
 	final ObjectProperty<Vault> vault = new SimpleObjectProperty<>();
 
 
 	@Inject
 	@Inject
-	public UnlockController(Application app, ExecutorService exec, WindowsDriveLetters driveLetters) {
+	public UnlockController(Application app, ExecutorService exec, Lazy<FrontendFactory> frontendFactory, WindowsDriveLetters driveLetters) {
 		this.app = app;
 		this.app = app;
 		this.exec = exec;
 		this.exec = exec;
+		this.frontendFactory = frontendFactory;
 		this.driveLetters = driveLetters;
 		this.driveLetters = driveLetters;
 	}
 	}
 
 
@@ -272,7 +276,7 @@ public class UnlockController extends AbstractFXMLViewController {
 
 
 	private void unlock(CharSequence password) {
 	private void unlock(CharSequence password) {
 		try {
 		try {
-			vault.get().activateFrontend(password);
+			vault.get().activateFrontend(frontendFactory.get(), password);
 			vault.get().reveal();
 			vault.get().reveal();
 		} catch (InvalidPassphraseException e) {
 		} catch (InvalidPassphraseException e) {
 			Platform.runLater(() -> {
 			Platform.runLater(() -> {

+ 3 - 6
main/ui/src/main/java/org/cryptomator/ui/model/Vault.java

@@ -45,7 +45,6 @@ import org.cryptomator.ui.util.FXThreads;
 
 
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableMap;
 
 
-import dagger.Lazy;
 import javafx.application.Platform;
 import javafx.application.Platform;
 import javafx.beans.property.BooleanProperty;
 import javafx.beans.property.BooleanProperty;
 import javafx.beans.property.SimpleBooleanProperty;
 import javafx.beans.property.SimpleBooleanProperty;
@@ -59,7 +58,6 @@ public class Vault implements Serializable, CryptoFileSystemDelegate {
 	public static final String VAULT_FILE_EXTENSION = ".cryptomator";
 	public static final String VAULT_FILE_EXTENSION = ".cryptomator";
 
 
 	private final Path path;
 	private final Path path;
-	private final Lazy<FrontendFactory> frontendFactory;
 	private final DeferredCloser closer;
 	private final DeferredCloser closer;
 	private final ShorteningFileSystemFactory shorteningFileSystemFactory;
 	private final ShorteningFileSystemFactory shorteningFileSystemFactory;
 	private final CryptoFileSystemFactory cryptoFileSystemFactory;
 	private final CryptoFileSystemFactory cryptoFileSystemFactory;
@@ -76,9 +74,8 @@ public class Vault implements Serializable, CryptoFileSystemDelegate {
 	/**
 	/**
 	 * Package private constructor, use {@link VaultFactory}.
 	 * Package private constructor, use {@link VaultFactory}.
 	 */
 	 */
-	Vault(Path vaultDirectoryPath, Lazy<FrontendFactory> frontendFactory, ShorteningFileSystemFactory shorteningFileSystemFactory, CryptoFileSystemFactory cryptoFileSystemFactory, DeferredCloser closer) {
+	Vault(Path vaultDirectoryPath, ShorteningFileSystemFactory shorteningFileSystemFactory, CryptoFileSystemFactory cryptoFileSystemFactory, DeferredCloser closer) {
 		this.path = vaultDirectoryPath;
 		this.path = vaultDirectoryPath;
-		this.frontendFactory = frontendFactory;
 		this.closer = closer;
 		this.closer = closer;
 		this.shorteningFileSystemFactory = shorteningFileSystemFactory;
 		this.shorteningFileSystemFactory = shorteningFileSystemFactory;
 		this.cryptoFileSystemFactory = cryptoFileSystemFactory;
 		this.cryptoFileSystemFactory = cryptoFileSystemFactory;
@@ -118,7 +115,7 @@ public class Vault implements Serializable, CryptoFileSystemDelegate {
 		}
 		}
 	}
 	}
 
 
-	public synchronized void activateFrontend(CharSequence passphrase) throws FrontendCreationFailedException {
+	public synchronized void activateFrontend(FrontendFactory frontendFactory, CharSequence passphrase) throws FrontendCreationFailedException {
 		boolean success = false;
 		boolean success = false;
 		try {
 		try {
 			FileSystem fs = getNioFileSystem();
 			FileSystem fs = getNioFileSystem();
@@ -127,7 +124,7 @@ public class Vault implements Serializable, CryptoFileSystemDelegate {
 			StatsFileSystem statsFs = new StatsFileSystem(cryptoFs);
 			StatsFileSystem statsFs = new StatsFileSystem(cryptoFs);
 			statsFileSystem = Optional.of(statsFs);
 			statsFileSystem = Optional.of(statsFs);
 			String contextPath = StringUtils.prependIfMissing(mountName, "/");
 			String contextPath = StringUtils.prependIfMissing(mountName, "/");
-			Frontend frontend = frontendFactory.get().create(statsFs, contextPath);
+			Frontend frontend = frontendFactory.create(statsFs, contextPath);
 			filesystemFrontend = closer.closeLater(frontend);
 			filesystemFrontend = closer.closeLater(frontend);
 			frontend.mount(getMountParams());
 			frontend.mount(getMountParams());
 			success = true;
 			success = true;

+ 2 - 7
main/ui/src/main/java/org/cryptomator/ui/model/VaultFactory.java

@@ -15,30 +15,25 @@ import javax.inject.Singleton;
 
 
 import org.cryptomator.filesystem.crypto.CryptoFileSystemFactory;
 import org.cryptomator.filesystem.crypto.CryptoFileSystemFactory;
 import org.cryptomator.filesystem.shortening.ShorteningFileSystemFactory;
 import org.cryptomator.filesystem.shortening.ShorteningFileSystemFactory;
-import org.cryptomator.frontend.FrontendFactory;
 import org.cryptomator.frontend.webdav.mount.WebDavMounter;
 import org.cryptomator.frontend.webdav.mount.WebDavMounter;
 import org.cryptomator.ui.util.DeferredCloser;
 import org.cryptomator.ui.util.DeferredCloser;
 
 
-import dagger.Lazy;
-
 @Singleton
 @Singleton
 public class VaultFactory {
 public class VaultFactory {
 
 
-	private final Lazy<FrontendFactory> frontendFactory;
 	private final ShorteningFileSystemFactory shorteningFileSystemFactory;
 	private final ShorteningFileSystemFactory shorteningFileSystemFactory;
 	private final CryptoFileSystemFactory cryptoFileSystemFactory;
 	private final CryptoFileSystemFactory cryptoFileSystemFactory;
 	private final DeferredCloser closer;
 	private final DeferredCloser closer;
 
 
 	@Inject
 	@Inject
-	public VaultFactory(Lazy<FrontendFactory> frontendFactory, ShorteningFileSystemFactory shorteningFileSystemFactory, CryptoFileSystemFactory cryptoFileSystemFactory, WebDavMounter mounter, DeferredCloser closer) {
-		this.frontendFactory = frontendFactory;
+	public VaultFactory(ShorteningFileSystemFactory shorteningFileSystemFactory, CryptoFileSystemFactory cryptoFileSystemFactory, WebDavMounter mounter, DeferredCloser closer) {
 		this.shorteningFileSystemFactory = shorteningFileSystemFactory;
 		this.shorteningFileSystemFactory = shorteningFileSystemFactory;
 		this.cryptoFileSystemFactory = cryptoFileSystemFactory;
 		this.cryptoFileSystemFactory = cryptoFileSystemFactory;
 		this.closer = closer;
 		this.closer = closer;
 	}
 	}
 
 
 	public Vault createVault(Path path) {
 	public Vault createVault(Path path) {
-		return new Vault(path, frontendFactory, shorteningFileSystemFactory, cryptoFileSystemFactory, closer);
+		return new Vault(path, shorteningFileSystemFactory, cryptoFileSystemFactory, closer);
 	}
 	}
 
 
 }
 }

+ 29 - 1
main/ui/src/main/java/org/cryptomator/ui/settings/Settings.java

@@ -14,17 +14,26 @@ import java.util.List;
 
 
 import org.cryptomator.ui.model.Vault;
 import org.cryptomator.ui.model.Vault;
 
 
+import com.fasterxml.jackson.annotation.JsonProperty;
 import com.fasterxml.jackson.annotation.JsonPropertyOrder;
 import com.fasterxml.jackson.annotation.JsonPropertyOrder;
 
 
-@JsonPropertyOrder(value = {"directories", "checkForUpdatesEnabled"})
+@JsonPropertyOrder(value = {"directories", "checkForUpdatesEnabled", "port"})
 public class Settings implements Serializable {
 public class Settings implements Serializable {
 
 
 	private static final long serialVersionUID = 7609959894417878744L;
 	private static final long serialVersionUID = 7609959894417878744L;
+	public static final int MIN_PORT = 1024;
+	public static final int MAX_PORT = 65535;
+	public static final int DEFAULT_PORT = 0;
 
 
+	@JsonProperty("directories")
 	private List<Vault> directories;
 	private List<Vault> directories;
 
 
+	@JsonProperty("checkForUpdatesEnabled")
 	private Boolean checkForUpdatesEnabled;
 	private Boolean checkForUpdatesEnabled;
 
 
+	@JsonProperty("port")
+	private Integer port;
+
 	/**
 	/**
 	 * Package-private constructor; use {@link SettingsProvider}.
 	 * Package-private constructor; use {@link SettingsProvider}.
 	 */
 	 */
@@ -54,4 +63,23 @@ public class Settings implements Serializable {
 		this.checkForUpdatesEnabled = checkForUpdatesEnabled;
 		this.checkForUpdatesEnabled = checkForUpdatesEnabled;
 	}
 	}
 
 
+	public void setPort(int port) {
+		if (!isPortValid(port)) {
+			throw new IllegalArgumentException("Invalid port");
+		}
+		this.port = port;
+	}
+
+	public int getPort() {
+		if (port == null || !isPortValid(port)) {
+			return DEFAULT_PORT;
+		} else {
+			return port;
+		}
+	}
+
+	private boolean isPortValid(int port) {
+		return port == DEFAULT_PORT || port >= MIN_PORT && port <= MAX_PORT;
+	}
+
 }
 }

+ 25 - 19
main/ui/src/main/resources/fxml/settings.fxml

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 <!--
-  Copyright (c) 2014 Sebastian Stenzel
+  Copyright (c) 2016 Sebastian Stenzel
   This file is licensed under the terms of the MIT license.
   This file is licensed under the terms of the MIT license.
   See the LICENSE.txt file for more info.
   See the LICENSE.txt file for more info.
   
   
@@ -13,23 +13,29 @@
 <?import javafx.scene.layout.ColumnConstraints?>
 <?import javafx.scene.layout.ColumnConstraints?>
 <?import javafx.scene.control.Label?>
 <?import javafx.scene.control.Label?>
 <?import javafx.scene.control.CheckBox?>
 <?import javafx.scene.control.CheckBox?>
+<?import javafx.scene.control.TextField?>
+<?import javafx.scene.layout.VBox?>
 
 
-<GridPane vgap="12.0" hgap="12.0" prefWidth="400.0" xmlns:fx="http://javafx.com/fxml" cacheShape="true" cache="true">
-	<padding>
-		<Insets top="24.0" right="24.0" bottom="24.0" left="24.0" />
-	</padding>
+<VBox prefWidth="400.0" alignment="TOP_CENTER" spacing="12.0" cacheShape="true" cache="true">
+	<GridPane VBox.vgrow="ALWAYS" vgap="12.0" hgap="12.0" xmlns:fx="http://javafx.com/fxml" cacheShape="true" cache="true">
+		<padding>
+			<Insets top="24.0" right="24.0" bottom="24.0" left="24.0" />
+		</padding>
+		
+		<columnConstraints>
+			<ColumnConstraints percentWidth="38.2"/>
+			<ColumnConstraints percentWidth="61.8"/>
+		</columnConstraints>
 	
 	
-	<columnConstraints>
-		<ColumnConstraints percentWidth="38.2"/>
-		<ColumnConstraints percentWidth="61.8"/>
-	</columnConstraints>
-
-	<children>
-		<!-- Row 0 -->
-		<Label GridPane.rowIndex="0" GridPane.columnIndex="0" text="%settings.checkForUpdates.label" cacheShape="true" cache="true" />
-		<CheckBox GridPane.rowIndex="0" GridPane.columnIndex="1" fx:id="checkForUpdatesCheckbox" cacheShape="true" cache="true" />
-	</children>
-</GridPane>
-
-
-					
+		<children>
+			<!-- Row 0 -->
+			<Label GridPane.rowIndex="0" GridPane.columnIndex="0" text="%settings.checkForUpdates.label" cacheShape="true" cache="true" />
+			<CheckBox GridPane.rowIndex="0" GridPane.columnIndex="1" fx:id="checkForUpdatesCheckbox" cacheShape="true" cache="true" />
+			
+			<!-- Row 1 -->
+			<Label GridPane.rowIndex="1" GridPane.columnIndex="0" text="%settings.port.label" cacheShape="true" cache="true" />
+			<TextField GridPane.rowIndex="1" GridPane.columnIndex="1" fx:id="portField" cacheShape="true" cache="true" promptText="%settings.port.prompt" />
+		</children>
+	</GridPane>
+	<Label VBox.vgrow="NEVER" text="%settings.requiresRestartLabel" alignment="CENTER" cacheShape="true" cache="true" />
+</VBox>			

+ 3 - 0
main/ui/src/main/resources/localization.properties

@@ -73,6 +73,9 @@ macWarnings.whitelistButton=Decrypt selected anyway
 
 
 # settings.fxml
 # settings.fxml
 settings.checkForUpdates.label=Check for updates
 settings.checkForUpdates.label=Check for updates
+settings.port.label=WebDAV Port *
+settings.port.prompt=0 = Choose automatically
+settings.requiresRestartLabel=* Restart required
 
 
 # tray icon
 # tray icon
 tray.menu.open=Open
 tray.menu.open=Open