implemented input validation

This commit is contained in:
Jan-Peter Klein
2025-03-04 15:23:01 +01:00
parent f3581c5acf
commit 1bc256c6d5
3 changed files with 136 additions and 14 deletions

View File

@@ -113,7 +113,12 @@ public class Settings {
migrateLegacySettings(json);
directories.addListener(this::somethingChanged);
networkSettings.addListener(this::somethingChanged);
networkSettings.get().mode.addListener(this::somethingChanged);
networkSettings.get().httpProxy.addListener(this::somethingChanged);
networkSettings.get().httpPort.addListener(this::somethingChanged);
networkSettings.get().samePortProxyForHttpHttps.addListener(this::somethingChanged);
networkSettings.get().httpsProxy.addListener(this::somethingChanged);
networkSettings.get().httpsPort.addListener(this::somethingChanged);
askedForUpdateCheck.addListener(this::somethingChanged);
checkForUpdates.addListener(this::somethingChanged);
startHidden.addListener(this::somethingChanged);

View File

@@ -1,42 +1,159 @@
package org.cryptomator.ui.preferences;
import org.cryptomator.common.settings.NetworkSettings;
import org.cryptomator.common.settings.Settings;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.controls.NumericTextField;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.StringProperty;
import javafx.fxml.FXML;
import javafx.scene.control.CheckBox;
import javafx.scene.control.RadioButton;
import javafx.scene.control.TextField;
import javafx.scene.control.ToggleGroup;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
@PreferencesScoped
public class NetworkPreferencesController implements FxController {
private static final Logger LOG = LoggerFactory.getLogger(NetworkPreferencesController.class);
private final Settings settings;
public ToggleGroup proxyToggleGroup;
public RadioButton noProxyBtn;
public RadioButton systemSettingsBtn;
public RadioButton manualProxyBtn;
public VBox manualProxyBox;
public NumericTextField httpProxyPort;
public NumericTextField httpsProxyPort;
public HBox httpsProxyBox;
@FXML
public TextField httpProxy;
public NumericTextField httpPort;
public CheckBox samePortProxyForHttpHttps;
public TextField httpsProxy;
public NumericTextField httpsPort;
@Inject
NetworkPreferencesController() {
NetworkPreferencesController(Settings settings) {
this.settings = settings;
}
@FXML
public void initialize() {
proxyToggleGroup.selectToggle(noProxyBtn);
initializeTextFieldWithValidation(httpProxy, settings.networkSettings.get().httpProxy);
initializeTextFieldWithValidation(httpPort, settings.networkSettings.get().httpPort);
initializeTextFieldWithValidation(httpsProxy, settings.networkSettings.get().httpsProxy);
initializeTextFieldWithValidation(httpsPort, settings.networkSettings.get().httpsPort);
samePortProxyForHttpHttps.selectedProperty().bindBidirectional(settings.networkSettings.get().samePortProxyForHttpHttps);
httpsProxyBox.setDisable(settings.networkSettings.get().samePortProxyForHttpHttps.get());
samePortProxyForHttpHttps.selectedProperty().addListener((_, _, newValue) -> {
httpsProxyBox.setDisable(newValue);
});
switch (settings.networkSettings.get().mode.get()) {
case NO -> {
proxyToggleGroup.selectToggle(noProxyBtn);
manualProxyBox.setDisable(true);
}
case SYSTEM -> {
proxyToggleGroup.selectToggle(systemSettingsBtn);
manualProxyBox.setDisable(true);
}
case MANUAL -> {
proxyToggleGroup.selectToggle(manualProxyBtn);
manualProxyBox.setDisable(false);
}
}
proxyToggleGroup.selectedToggleProperty().addListener((_, _, newValue) -> {
if (newValue != null) {
RadioButton selectedRadioButton = (RadioButton) newValue;
manualProxyBox.setDisable(!selectedRadioButton.equals(manualProxyBtn));
manualProxyBox.setDisable(!newValue.equals(manualProxyBtn));
if (newValue.equals(noProxyBtn)) {
settings.networkSettings.get().mode.set(NetworkSettings.ProxyMode.NO);
} else if (newValue.equals(systemSettingsBtn)) {
settings.networkSettings.get().mode.set(NetworkSettings.ProxyMode.SYSTEM);
} else if (newValue.equals(manualProxyBtn)) {
settings.networkSettings.get().mode.set(NetworkSettings.ProxyMode.MANUAL);
}
}
});
}
private void initializeTextFieldWithValidation(TextField textField, StringProperty property) {
textField.setText(property.get());
textField.textProperty().addListener((_, _, newValue) -> {
if (isValidHttpProxy(newValue)) {
textField.setStyle("-fx-border-color: green; -fx-border-width: 2px; -fx-border-radius: 3px; -fx-padding: 3px;");
} else {
textField.setStyle("-fx-border-color: red; -fx-border-width: 2px; -fx-border-radius: 3px; -fx-padding: 3px;");
}
});
textField.focusedProperty().addListener((_, oldValue, newValue) -> {
if (!newValue) {
String text = textField.getText();
if (isValidHttpProxy(text)) {
property.set(text);
textField.setStyle("");
}
}
});
}
private boolean isValidHttpProxy(String text) {
if (text == null || text.isEmpty()) {
return false;
}
String regex = "^([\\w.-]+)$";
return text.matches(regex);
}
private void initializeTextFieldWithValidation(TextField textField, IntegerProperty property) {
textField.setText(String.valueOf(property.get()));
textField.textProperty().addListener((observable, oldValue, newValue) -> {
if (isValidPort(newValue)) {
textField.setStyle("-fx-border-color: green; -fx-border-width: 2px; -fx-border-radius: 3px; -fx-padding: 3px;");
} else {
textField.setStyle("-fx-border-color: red; -fx-border-width: 2px; -fx-border-radius: 3px; -fx-padding: 3px;");
}
});
textField.focusedProperty().addListener((_, _, newValue) -> {
if (!newValue) {
String text = textField.getText();
if (isValidPort(text)) {
property.set(Integer.parseInt(text));
textField.setText(removeLeadingZeros(textField.getText()));
textField.setStyle("");
}
}
});
}
public static String removeLeadingZeros(String str) {
if (str == null || str.isEmpty()) {
return str;
}
return str.replaceFirst("^0+(?!$)", "");
}
private boolean isValidPort(String text) {
if (text == null || text.isEmpty()) {
return false;
}
try {
int value = Integer.parseInt(text);
return value >= 1024 && value <= 8888;
} catch (NumberFormatException e) {
return false;
}
}
}

View File

@@ -33,14 +33,14 @@
<Label text="HTTP Proxy" minWidth="90" />
<TextField fx:id="httpProxy" HBox.hgrow="ALWAYS" />
<Label text="Port"/>
<NumericTextField fx:id="httpProxyPort" prefWidth="60" promptText="0" />
<NumericTextField fx:id="httpPort" prefWidth="60" promptText="0" />
</HBox>
<CheckBox text="Also use this proxy for HTTPS"/>
<HBox spacing="12" alignment="CENTER_LEFT">
<CheckBox fx:id="samePortProxyForHttpHttps" text="Also use this proxy for HTTPS"/>
<HBox fx:id="httpsProxyBox" spacing="12" alignment="CENTER_LEFT">
<Label text="HTTPS Proxy" minWidth="90"/>
<TextField fx:id="httpsProxy" HBox.hgrow="ALWAYS" />
<Label text="Port"/>
<NumericTextField fx:id="httpsProxyPort" prefWidth="60" promptText="0"/>
<NumericTextField fx:id="httpsPort" prefWidth="60" promptText="0"/>
</HBox>
</VBox>