应用数据本地加密存储
添加记住密码、自动登录、找回密码 修复点击隧道列表时隧道设置显示bug
This commit is contained in:
parent
269c1c1299
commit
2c327bbd69
2
pom.xml
2
pom.xml
@ -6,7 +6,7 @@
|
||||
|
||||
<groupId>top.octopusyan</groupId>
|
||||
<artifactId>YanFrp</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>0.1.2-SNAPSHOT</version>
|
||||
<name>YanFrp</name>
|
||||
|
||||
<properties>
|
||||
|
@ -3,7 +3,6 @@ package top.octopusyan;
|
||||
import javafx.application.Application;
|
||||
import javafx.application.Platform;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.fxml.JavaFXBuilderFactory;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.layout.StackPane;
|
||||
import javafx.scene.paint.Color;
|
||||
@ -12,13 +11,14 @@ import javafx.stage.StageStyle;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import top.octopusyan.base.BaseController;
|
||||
import top.octopusyan.http.OkHttpClientConfig;
|
||||
import top.octopusyan.manager.FrpManager;
|
||||
import top.octopusyan.manager.http.HttpConfig;
|
||||
import top.octopusyan.manager.http.config.LogStrategy;
|
||||
import top.octopusyan.manager.http.request.RequestHandler;
|
||||
import top.octopusyan.http.OkHttpClientConfig;
|
||||
import top.octopusyan.model.ApplicatonStore;
|
||||
import top.octopusyan.utils.AlertUtil;
|
||||
import top.octopusyan.utils.ApplicatonStore;
|
||||
import top.octopusyan.utils.FrpUtil;
|
||||
import top.octopusyan.utils.EncryptionUtil;
|
||||
import top.octopusyan.utils.FxmlUtil;
|
||||
|
||||
/**
|
||||
@ -35,8 +35,14 @@ public class YanFrpApplication extends Application {
|
||||
super.init();
|
||||
logger.info("init...");
|
||||
|
||||
// 初始化加密工具
|
||||
EncryptionUtil.init();
|
||||
|
||||
// 初始化应用数据
|
||||
ApplicatonStore.init();
|
||||
|
||||
// 初始化frp客户端临时文件
|
||||
FrpUtil.initFrpc();
|
||||
FrpManager.initFrpc();
|
||||
|
||||
// 网络请求设置
|
||||
HttpConfig.with(OkHttpClientConfig.httpClient())
|
||||
@ -64,8 +70,6 @@ public class YanFrpApplication extends Application {
|
||||
|
||||
// 初始化弹窗
|
||||
AlertUtil.initOwner(stage);
|
||||
// 初始化应用数据
|
||||
ApplicatonStore.setRegisterSuccess(false);
|
||||
|
||||
try {
|
||||
// 静态写法无法获取controler
|
||||
@ -102,7 +106,7 @@ public class YanFrpApplication extends Application {
|
||||
@Override
|
||||
public void stop() throws Exception {
|
||||
super.stop();
|
||||
FrpUtil.clearTmp();
|
||||
FrpManager.clearTmp();
|
||||
logger.info("stop...");
|
||||
}
|
||||
|
||||
|
@ -1,24 +1,9 @@
|
||||
package top.octopusyan;
|
||||
|
||||
import javafx.application.Application;
|
||||
import javafx.application.Platform;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.layout.StackPane;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.stage.Stage;
|
||||
import javafx.stage.StageStyle;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import top.octopusyan.base.BaseController;
|
||||
import top.octopusyan.http.OkHttpClientConfig;
|
||||
import top.octopusyan.manager.http.HttpConfig;
|
||||
import top.octopusyan.manager.http.config.LogStrategy;
|
||||
import top.octopusyan.manager.http.request.RequestHandler;
|
||||
import top.octopusyan.utils.AlertUtil;
|
||||
import top.octopusyan.utils.ApplicatonStore;
|
||||
import top.octopusyan.utils.FrpUtil;
|
||||
import top.octopusyan.utils.FxmlUtil;
|
||||
import top.octopusyan.manager.FrpManager;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author : octopus yan
|
||||
@ -28,6 +13,12 @@ import top.octopusyan.utils.FxmlUtil;
|
||||
*/
|
||||
public class YanFrpLuncher {
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
Runtime.getRuntime().exec("Taskkill /IM " + FrpManager.FRPC_CLIENT_FILE_NAME + " /f");
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
Application.launch(YanFrpApplication.class, args);
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,9 @@ import javafx.scene.layout.Pane;
|
||||
import javafx.stage.Stage;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import top.octopusyan.manager.FrpManager;
|
||||
import top.octopusyan.manager.http.EasyHttp;
|
||||
import top.octopusyan.model.ApplicatonStore;
|
||||
import top.octopusyan.utils.FxmlUtil;
|
||||
import top.octopusyan.utils.Loading;
|
||||
|
||||
@ -184,11 +187,18 @@ public abstract class BaseController<P extends Pane> implements Initializable {
|
||||
* 关闭窗口
|
||||
*/
|
||||
public void onDestroy() {
|
||||
// 取消所有请求
|
||||
EasyHttp.cancel();
|
||||
// 停止所有代理隧道
|
||||
FrpManager.frpcList.forEach(FrpManager::stop);
|
||||
// 保存应用数据
|
||||
ApplicatonStore.save();
|
||||
|
||||
Stage stage = (Stage) getRootPanel().getScene().getWindow();
|
||||
stage.hide();
|
||||
stage.close();
|
||||
try {
|
||||
Thread.sleep(2000);
|
||||
Thread.sleep(1000);
|
||||
Platform.exit();
|
||||
System.exit(0);
|
||||
} catch (InterruptedException e) {
|
||||
|
@ -31,6 +31,7 @@ public class ProxyConfig {
|
||||
typePort.put("https", 80);
|
||||
typePort.put("ssh", 22);
|
||||
typePort.put("tcp", 0);
|
||||
typePort.put("udp", 0);
|
||||
}
|
||||
|
||||
|
||||
@ -60,6 +61,7 @@ public class ProxyConfig {
|
||||
HTTPS("https"),
|
||||
SSH("tcp"),
|
||||
TCP("tcp"),
|
||||
UDP("udp"),
|
||||
;
|
||||
|
||||
private final String type;
|
||||
|
@ -4,7 +4,6 @@ import com.jfoenix.validation.RegexValidator;
|
||||
import com.jfoenix.validation.RequiredFieldValidator;
|
||||
import com.jfoenix.validation.StringLengthValidator;
|
||||
import com.jfoenix.validation.base.ValidatorBase;
|
||||
import top.octopusyan.config.ProxyConfig;
|
||||
import top.octopusyan.model.ProxySetupModel;
|
||||
import top.octopusyan.utils.DomainUtil;
|
||||
|
||||
@ -100,12 +99,19 @@ public class TextValidate {
|
||||
*/
|
||||
public static ValidatorBase domainFormatValidator(ProxySetupModel model) {
|
||||
|
||||
return new ValidatorBase("域名格式错误") {
|
||||
return new ValidatorBase("域名格式错误,支持数字字母下划线") {
|
||||
@Override
|
||||
protected void eval() {
|
||||
if (!DomainUtil.isCustomize(model.get()))
|
||||
hasErrors.set(false);
|
||||
else {
|
||||
if (!DomainUtil.isCustomize(model.get())) {
|
||||
if (DomainUtil.isHttp(model)) {
|
||||
// http / https
|
||||
boolean matches = Pattern.compile("^[a-zA-Z0-9_-]{3,18}$").matcher(model.getDomain()).matches();
|
||||
hasErrors.set(!matches);
|
||||
} else {
|
||||
// tcp / udp
|
||||
hasErrors.set(false);
|
||||
}
|
||||
} else {
|
||||
boolean matches = Pattern.compile("^(?=^.{3,255}$)[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+$")
|
||||
.matcher(model.getDomain() + model.getDomainSuffix()).matches();
|
||||
hasErrors.set(!matches);
|
||||
@ -119,7 +125,7 @@ public class TextValidate {
|
||||
*/
|
||||
public static ValidatorBase domainLengthValidator(ProxySetupModel model) {
|
||||
|
||||
return new RegexValidator("请输入子域名,长度不小于3个字符") {
|
||||
return new RegexValidator("子域名长度不小于3个字符") {
|
||||
@Override
|
||||
protected void eval() {
|
||||
setRegexPattern("^[a-zA-Z0-9_-]{3,18}$");
|
||||
|
@ -5,6 +5,7 @@ import com.jfoenix.controls.JFXCheckBox;
|
||||
import com.jfoenix.controls.JFXPasswordField;
|
||||
import com.jfoenix.controls.JFXTextField;
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.control.Button;
|
||||
@ -17,14 +18,18 @@ import org.apache.commons.lang3.StringUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.kordamp.ikonli.javafx.FontIcon;
|
||||
import top.octopusyan.base.BaseController;
|
||||
import top.octopusyan.config.TextValidate;
|
||||
import top.octopusyan.http.Api;
|
||||
import top.octopusyan.http.request.FindPassParam;
|
||||
import top.octopusyan.http.request.LoginParam;
|
||||
import top.octopusyan.manager.ProxyManager;
|
||||
import top.octopusyan.manager.http.EasyHttp;
|
||||
import top.octopusyan.manager.http.api.NotParamApi;
|
||||
import top.octopusyan.manager.http.config.HttpConstant;
|
||||
import top.octopusyan.manager.http.listener.OnHttpListener;
|
||||
import top.octopusyan.config.TextValidate;
|
||||
import top.octopusyan.http.Api;
|
||||
import top.octopusyan.http.request.LoginParam;
|
||||
import top.octopusyan.utils.*;
|
||||
import top.octopusyan.model.ApplicatonStore;
|
||||
import top.octopusyan.utils.AlertUtil;
|
||||
import top.octopusyan.utils.JsoupUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@ -69,8 +74,10 @@ public class LoginController extends BaseController<StackPane> implements Initia
|
||||
public JFXCheckBox autoLoginCBox;
|
||||
@FXML
|
||||
public JFXCheckBox rememberCBox;
|
||||
@FXML
|
||||
public JFXButton findpassBtn;
|
||||
|
||||
private boolean autoLogin;
|
||||
private SimpleStringProperty tmppwd = new SimpleStringProperty();
|
||||
|
||||
@Override
|
||||
public boolean dragWindow() {
|
||||
@ -105,19 +112,27 @@ public class LoginController extends BaseController<StackPane> implements Initia
|
||||
|
||||
@Override
|
||||
public void initData() {
|
||||
String account = ApplicatonStore.getAccount();
|
||||
String password = ApplicatonStore.getPassword();
|
||||
// 数据绑定
|
||||
// 账号
|
||||
accountTextField.textProperty().bindBidirectional(ApplicatonStore.accountProperty());
|
||||
// 密码
|
||||
if (ApplicatonStore.isRememberMe()) tmppwd.set(ApplicatonStore.getPassword());
|
||||
// 自动登录
|
||||
autoLoginCBox.selectedProperty().bindBidirectional(ApplicatonStore.autoLoginProperty());
|
||||
// 记住我
|
||||
rememberCBox.selectedProperty().bindBidirectional(ApplicatonStore.rememberMeProperty());
|
||||
|
||||
|
||||
passwordTextField.textProperty().bindBidirectional(tmppwd);
|
||||
seePwdTextField.textProperty().bindBidirectional(tmppwd);
|
||||
|
||||
if (!StringUtils.isEmpty(account)) accountTextField.setText(account);
|
||||
if (!StringUtils.isEmpty(password)) {
|
||||
passwordTextField.setText(password);
|
||||
seePwdTextField.setText(password);
|
||||
}
|
||||
}
|
||||
|
||||
// 隐藏展示密码框
|
||||
private AnchorPane pwdParent;
|
||||
|
||||
private AlertUtil.Builder findpassAlert;
|
||||
|
||||
@Override
|
||||
public void initViewStyle() {
|
||||
|
||||
@ -136,11 +151,6 @@ public class LoginController extends BaseController<StackPane> implements Initia
|
||||
pwdParent = (AnchorPane) passwordTextField.getParent();
|
||||
pwdParent.getChildren().remove(seePwdTextField);
|
||||
|
||||
// 同步用户数据
|
||||
accountTextField.textProperty().addListener((observable, oldValue, newValue) -> ApplicatonStore.setAccount(newValue));
|
||||
passwordTextField.textProperty().addListener((observable, oldValue, newValue) -> ApplicatonStore.setPassword(newValue));
|
||||
seePwdTextField.textProperty().addListener((observable, oldValue, newValue) -> ApplicatonStore.setPassword(newValue));
|
||||
|
||||
// 添加文本校验
|
||||
accountTextField.getValidators().add(TextValidate.AccoountRequired);
|
||||
accountTextField.getValidators().add(TextValidate.AccoountValidator);
|
||||
@ -148,12 +158,9 @@ public class LoginController extends BaseController<StackPane> implements Initia
|
||||
passwordTextField.getValidators().add(TextValidate.PasswordRequired);
|
||||
seePwdTextField.getValidators().add(TextValidate.PasswordRequired);
|
||||
|
||||
// 记住密码
|
||||
rememberCBox.selectedProperty().addListener((observable, oldValue, newValue) -> ApplicatonStore.setRememberMe(newValue));
|
||||
// 自动登录
|
||||
autoLoginCBox.selectedProperty().addListener((observable, oldValue, newValue) -> {
|
||||
ApplicatonStore.setAutoLogin(newValue);
|
||||
if (newValue && !ApplicatonStore.isRememberMe()) rememberCBox.selectedProperty().set(true);
|
||||
if (newValue) ApplicatonStore.setRememberMe(true);
|
||||
});
|
||||
}
|
||||
|
||||
@ -162,6 +169,7 @@ public class LoginController extends BaseController<StackPane> implements Initia
|
||||
|
||||
// 注册
|
||||
registerBtn.setOnMouseClicked(event -> {
|
||||
ApplicatonStore.setPassword(tmppwd.get());
|
||||
try {
|
||||
jumpTo(new RegisterController());
|
||||
} catch (IOException e) {
|
||||
@ -175,7 +183,7 @@ public class LoginController extends BaseController<StackPane> implements Initia
|
||||
|
||||
pwdParent.getChildren().remove(isHide ? passwordTextField : seePwdTextField);
|
||||
pwdParent.getChildren().add(1, isHide ? seePwdTextField : passwordTextField);
|
||||
(isHide ? seePwdTextField : passwordTextField).setText(ApplicatonStore.getPassword());
|
||||
(isHide ? seePwdTextField : passwordTextField).setText(tmppwd.get());
|
||||
seePwdIcon.setIconColor(isHide ? Color.BLUE : Color.BLACK);
|
||||
});
|
||||
|
||||
@ -188,6 +196,14 @@ public class LoginController extends BaseController<StackPane> implements Initia
|
||||
if (event.getCode() == KeyCode.ENTER) login();
|
||||
});
|
||||
|
||||
// 找回密码
|
||||
findpassBtn.setOnMouseClicked(event -> {
|
||||
findpassAlert = AlertUtil.input("请输入您的账号或邮箱")
|
||||
.title("找回密码")
|
||||
.header(null);
|
||||
findpass(findpassAlert.getInput());
|
||||
});
|
||||
|
||||
// 自动登录
|
||||
if ((ApplicatonStore.isAutoLogin() || ApplicatonStore.isRegisterSuccess()) &&
|
||||
!StringUtils.isEmpty(ApplicatonStore.getAccount()) &&
|
||||
@ -197,6 +213,33 @@ public class LoginController extends BaseController<StackPane> implements Initia
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 找回密码
|
||||
*/
|
||||
private void findpass(String input) {
|
||||
if (StringUtils.isNotEmpty(input))
|
||||
EasyHttp.builder()
|
||||
.api(Api.findpass)
|
||||
.param(new FindPassParam(input))
|
||||
.request(new OnHttpListener<String>() {
|
||||
@Override
|
||||
public void onSucceed(String result) {
|
||||
Platform.runLater(() -> {
|
||||
if (JsoupUtil.isAlertSuccess(result)) {
|
||||
AlertUtil.info(JsoupUtil.getSuccessMessage(result)).show();
|
||||
} else {
|
||||
AlertUtil.error(JsoupUtil.getErrorMessage(result)).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFail(Exception e) {
|
||||
Platform.runLater(() -> AlertUtil.exceptionAlert(e).show());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void login() {
|
||||
|
||||
// 获取文本校验结果
|
||||
@ -207,7 +250,7 @@ public class LoginController extends BaseController<StackPane> implements Initia
|
||||
if (pwdValidate && accountValidate)
|
||||
EasyHttp.builder()
|
||||
.api(Api.Login)
|
||||
.param(new LoginParam(accountTextField.getText(), ApplicatonStore.getPassword()))
|
||||
.param(new LoginParam(accountTextField.getText(), tmppwd.get()))
|
||||
.request(new OnHttpListener<String>() {
|
||||
@Override
|
||||
public void onSucceed(String result) {
|
||||
@ -216,8 +259,11 @@ public class LoginController extends BaseController<StackPane> implements Initia
|
||||
Platform.runLater(() -> AlertUtil.error(JsoupUtil.getErrorMessage(result)).show());
|
||||
return;
|
||||
}
|
||||
// TODO 登录成功
|
||||
// 登录成功
|
||||
setCsrf();
|
||||
// 记住我
|
||||
ApplicatonStore.rememberMe(tmppwd.get());
|
||||
// 跳转
|
||||
Platform.runLater(() -> {
|
||||
try {
|
||||
jumpTo(new MainController());
|
||||
@ -243,7 +289,7 @@ public class LoginController extends BaseController<StackPane> implements Initia
|
||||
.request(new OnHttpListener<String>() {
|
||||
@Override
|
||||
public void onSucceed(String result) {
|
||||
ProxyUtil.setCsrf(result);
|
||||
ProxyManager.setCsrf(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -255,7 +301,6 @@ public class LoginController extends BaseController<StackPane> implements Initia
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
EasyHttp.cancel();
|
||||
super.onDestroy();
|
||||
}
|
||||
}
|
||||
|
@ -1,23 +1,17 @@
|
||||
package top.octopusyan.controller;
|
||||
|
||||
import com.jfoenix.controls.*;
|
||||
import com.jfoenix.validation.IntegerValidator;
|
||||
import com.jfoenix.validation.RequiredFieldValidator;
|
||||
import javafx.application.HostServices;
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.beans.property.SimpleIntegerProperty;
|
||||
import javafx.beans.value.ChangeListener;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.control.*;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.input.MouseEvent;
|
||||
import javafx.scene.control.*;
|
||||
import javafx.scene.layout.AnchorPane;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.StackPane;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@ -26,21 +20,24 @@ import top.octopusyan.base.BaseController;
|
||||
import top.octopusyan.config.ProxyConfig;
|
||||
import top.octopusyan.config.ProxyConfig.ProxyServer;
|
||||
import top.octopusyan.config.ProxyConfig.ProxyType;
|
||||
import top.octopusyan.config.TextValidate;
|
||||
import top.octopusyan.http.request.ProxySetup;
|
||||
import top.octopusyan.manager.FrpManager;
|
||||
import top.octopusyan.manager.ProxyManager;
|
||||
import top.octopusyan.manager.http.listener.OnHttpListener;
|
||||
import top.octopusyan.model.ApplicatonStore;
|
||||
import top.octopusyan.model.ProxySetupModel;
|
||||
import top.octopusyan.utils.AlertUtil;
|
||||
import top.octopusyan.utils.DomainUtil;
|
||||
import top.octopusyan.utils.FrpUtil;
|
||||
import top.octopusyan.utils.ProxyUtil;
|
||||
import top.octopusyan.config.TextValidate;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.datatransfer.Clipboard;
|
||||
import java.awt.datatransfer.StringSelection;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
import static top.octopusyan.model.ApplicatonStore.*;
|
||||
|
||||
/**
|
||||
* @author : octopus yan
|
||||
@ -55,7 +52,6 @@ public class MainController extends BaseController<StackPane> implements Initial
|
||||
public static final String PROXY_LIST_ITEM_RUN_CLASS = "proxyListItem-run";
|
||||
public static final String PROXY_LIST_ITEM_CLOSE_CLASS = "proxyListItem-close";
|
||||
public static final String PROXY_LIST_ITEM_SELECT_CLASS = "proxyListItem-select";
|
||||
public static final String INPUT_LEFT_CLASS = "inputText-left";
|
||||
public static final String INPUT_CLASS = "inputText";
|
||||
|
||||
@FXML
|
||||
@ -94,15 +90,15 @@ public class MainController extends BaseController<StackPane> implements Initial
|
||||
public Hyperlink domainLink;
|
||||
@FXML
|
||||
public HBox proxyStatusPane;
|
||||
@FXML
|
||||
public JFXButton logoutBtn;
|
||||
|
||||
private ToggleGroup openProxyGroup = new ToggleGroup();
|
||||
private SimpleBooleanProperty customizeDomain = new SimpleBooleanProperty(false);
|
||||
private List<ProxySetup> proxyList = new ArrayList<>();
|
||||
private Map<String, FrpUtil> frpUtilMap = new HashMap<>();
|
||||
private SimpleIntegerProperty selectProxy = new SimpleIntegerProperty(0);
|
||||
private Map<String, FrpManager> frpUtilMap = new HashMap<>();
|
||||
private ProxySetupModel proxySetupModel;
|
||||
private ProxySetup proxySetup;
|
||||
private SimpleBooleanProperty setting = new SimpleBooleanProperty(false);
|
||||
private SimpleBooleanProperty setup = new SimpleBooleanProperty(false);
|
||||
|
||||
@Override
|
||||
public boolean dragWindow() {
|
||||
@ -138,8 +134,12 @@ public class MainController extends BaseController<StackPane> implements Initial
|
||||
@Override
|
||||
public void initData() {
|
||||
// 初始化视图模型
|
||||
proxySetup = ProxyUtil.initProxy(null);
|
||||
proxySetup = ProxyManager.initProxy(null);
|
||||
proxySetupModel = new ProxySetupModel(proxySetup);
|
||||
// 初始化用户隧道列表
|
||||
setProxyList(Collections.singletonList(proxySetup));
|
||||
// 重置隧道列表视图
|
||||
initProxyListView();
|
||||
|
||||
// 隧道类型
|
||||
Arrays.asList(ProxyType.values()).forEach((type) -> proxyProtocolComboBox.getItems().add(type.name()));
|
||||
@ -148,24 +148,26 @@ public class MainController extends BaseController<StackPane> implements Initial
|
||||
Arrays.asList(ProxyServer.values()).forEach((server) -> proxyServerComboBox.getItems().add(server.getServerName()));
|
||||
|
||||
// 获取用户隧道列表
|
||||
ProxyUtil.getList(new OnHttpListener<List<ProxySetup>>() {
|
||||
ProxyManager.getList(new OnHttpListener<List<ProxySetup>>() {
|
||||
@Override
|
||||
public void onSucceed(List<ProxySetup> result) {
|
||||
|
||||
if (result != null)
|
||||
proxyList = result;
|
||||
Platform.runLater(() -> {
|
||||
|
||||
// 如果用户隧道列表不为空
|
||||
if (proxyList != null && proxyList.size() > 0) {
|
||||
// 显示隧道列表
|
||||
initProxyList(proxyList);
|
||||
// 默认选中第一个(配置隧道设置模型)
|
||||
proxyListView.getSelectionModel().select(0);
|
||||
} else {
|
||||
// 配置隧道设置模型
|
||||
proxyList = new ArrayList<>();
|
||||
proxyList.add(proxySetup);
|
||||
}
|
||||
// 如果用户隧道列表不为空
|
||||
if (result != null && result.size() > 0) {
|
||||
proxySetup = result.get(selectProxy());
|
||||
proxySetupModel.set(result.get(selectProxy()));
|
||||
// 初始化用户隧道列表
|
||||
setProxyList(result);
|
||||
// 重置隧道列表视图
|
||||
initProxyListView();
|
||||
}
|
||||
// else {
|
||||
// }
|
||||
//
|
||||
// bindDataView();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -199,6 +201,8 @@ public class MainController extends BaseController<StackPane> implements Initial
|
||||
|
||||
@Override
|
||||
public void initViewStyle() {
|
||||
// 设置列表
|
||||
proxyListView.getSelectionModel().select(0);
|
||||
// 启用链接
|
||||
openProxyRBtn.setToggleGroup(openProxyGroup);
|
||||
closeProxyRBtn.setToggleGroup(openProxyGroup);
|
||||
@ -232,7 +236,8 @@ public class MainController extends BaseController<StackPane> implements Initial
|
||||
|
||||
// 隧道名称
|
||||
proxySetupModel.proxyNameProperty().addListener((observable, oldValue, newValue) -> {
|
||||
proxyListView.getItems().get(selectProxy.get()).setText(newValue);
|
||||
if (proxyListView.getItems().size() > 0)
|
||||
proxyListView.getItems().get(selectProxy()).setText(newValue);
|
||||
});
|
||||
|
||||
// 运行状态监听
|
||||
@ -245,42 +250,29 @@ public class MainController extends BaseController<StackPane> implements Initial
|
||||
startProxyBtn.getStyleClass().add(newValue ? stopClass : startClass);
|
||||
startProxyBtn.setText(newValue ? "停止" : "启动");
|
||||
// 列表显示
|
||||
ObservableList<String> styleClass = proxyListView.getItems().get(selectProxy.get()).getStyleClass();
|
||||
ObservableList<String> styleClass = proxyListView.getItems().get(selectProxy()).getStyleClass();
|
||||
styleClass.remove(PROXY_LIST_ITEM_RUN_CLASS);
|
||||
styleClass.remove(PROXY_LIST_ITEM_STOP_CLASS);
|
||||
styleClass.add(newValue ? PROXY_LIST_ITEM_RUN_CLASS : PROXY_LIST_ITEM_STOP_CLASS);
|
||||
|
||||
// 外网访问连接
|
||||
if (DomainUtil.isHttp(proxySetupModel)) {
|
||||
// http / TODO https
|
||||
// String prefix = DomainUtil.isHttps(proxySetupModel) ? "https://" : "http://";
|
||||
// domainLink.textProperty().set(prefix + proxySetupModel.getDomain() + proxySetupModel.getDomainSuffix());
|
||||
domainLink.textProperty().set(proxySetupModel.getDomain() + proxySetupModel.getDomainSuffix());
|
||||
} else {
|
||||
// ssh / tcp
|
||||
domainLink.textProperty().set(ProxyConfig.getServerIP(ProxyConfig.getServerNode(proxySetupModel.getServer())) + ":" + proxySetupModel.getRemotePort());
|
||||
}
|
||||
setDomainLink();
|
||||
});
|
||||
|
||||
// 自定义外网访问地址按钮
|
||||
customizeDomain.addListener((observable, oldValue, newValue) -> {
|
||||
HBox parent = (HBox) domainTextField.getParent();
|
||||
ObservableList<String> styleClass = domainTextField.getStyleClass();
|
||||
styleClass.remove(INPUT_LEFT_CLASS);
|
||||
styleClass.remove(INPUT_CLASS);
|
||||
AnchorPane parent = (AnchorPane) domainTextField.getParent();
|
||||
// 是否切换为自定义域名
|
||||
if (newValue) {
|
||||
// 隐藏系统域名
|
||||
if (parent.getChildren().contains(domainSuffixTextField))
|
||||
parent.getChildren().remove(domainSuffixTextField);
|
||||
// 用户域名是否自定义
|
||||
if (!DomainUtil.isCustomize(proxySetup)) {
|
||||
if (!DomainUtil.isCustomize(proxySetupModel.get())) {
|
||||
proxySetupModel.setDomain("");
|
||||
} else {
|
||||
proxySetupModel.setDomain(proxySetup.getDomain());
|
||||
proxySetupModel.setDomain(proxySetupModel.getDomain());
|
||||
}
|
||||
proxySetupModel.setDomainSuffix("");
|
||||
styleClass.add(INPUT_CLASS);
|
||||
domainTextField.promptTextProperty().set("自定义域名");
|
||||
customizeDomainBtn.setText("系统分配");
|
||||
domainHtinTextField.setText("请输入您的域名,并解析至: " + ProxyConfig.getServerIP(proxySetupModel.getServer()));
|
||||
@ -289,14 +281,13 @@ public class MainController extends BaseController<StackPane> implements Initial
|
||||
if (!parent.getChildren().contains(domainSuffixTextField))
|
||||
parent.getChildren().add(domainSuffixTextField);
|
||||
// 用户域名是否自定义
|
||||
if (DomainUtil.isCustomize(proxySetup)) {
|
||||
if (DomainUtil.isCustomize(proxySetupModel.get())) {
|
||||
proxySetupModel.setDomain("");
|
||||
proxySetupModel.setDomainSuffix("." + ProxyConfig.getServerPath(proxySetupModel.getServer()));
|
||||
} else {
|
||||
proxySetupModel.setDomain(DomainUtil.getCustomize(proxySetup));
|
||||
proxySetupModel.setDomain(DomainUtil.getCustomize(proxySetupModel.get()));
|
||||
proxySetupModel.setDomainSuffix(DomainUtil.getSuffix(proxySetup));
|
||||
}
|
||||
styleClass.add(INPUT_LEFT_CLASS);
|
||||
domainTextField.promptTextProperty().set("自定义子域名 大于3位");
|
||||
customizeDomainBtn.setText("自定义");
|
||||
domainHtinTextField.setText("请输入子域名,长度不小于3个字符");
|
||||
@ -307,10 +298,27 @@ public class MainController extends BaseController<StackPane> implements Initial
|
||||
tabPane.getSelectionModel().select(1);
|
||||
}
|
||||
|
||||
/** 设置访问链接 */
|
||||
private void setDomainLink() {
|
||||
// 外网访问连接
|
||||
if (DomainUtil.isHttp(proxySetupModel)) {
|
||||
// http / https
|
||||
String prefix = proxySetupModel.getProxyType() + "://";
|
||||
domainLink.textProperty().set(prefix + proxySetupModel.getDomain() + proxySetupModel.getDomainSuffix());
|
||||
} else {
|
||||
// ssh / tcp
|
||||
domainLink.textProperty().set(ProxyConfig.getServerIP(ProxyConfig.getServerNode(proxySetupModel.getServer())) + ":" + proxySetupModel.getRemotePort());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initViewAction() {
|
||||
// 重置
|
||||
resetProxyBtn.setOnMouseClicked(event -> proxySetupModel.set(proxySetup));
|
||||
resetProxyBtn.setOnMouseClicked(event -> {
|
||||
proxySetup.setRuning(false);
|
||||
proxySetupModel.set(proxySetup);
|
||||
domainTextField.resetValidation();
|
||||
});
|
||||
|
||||
// 日志清理
|
||||
clearLogBtn.setOnMouseClicked(event -> {
|
||||
@ -360,7 +368,7 @@ public class MainController extends BaseController<StackPane> implements Initial
|
||||
});
|
||||
|
||||
// 域名检查
|
||||
setting.addListener((observable, oldValue, newValue) -> {
|
||||
setup.addListener((observable, oldValue, newValue) -> {
|
||||
if (newValue) domainTextField.validate();
|
||||
});
|
||||
domainTextField.textProperty().addListener((observable, oldValue, newValue) -> {
|
||||
@ -376,6 +384,9 @@ public class MainController extends BaseController<StackPane> implements Initial
|
||||
// 点击隧道列表
|
||||
proxyListView.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
|
||||
ObservableList<Label> items = proxyListView.getItems();
|
||||
|
||||
if (items.size() == 0) return;
|
||||
|
||||
for (Label item : items) {
|
||||
item.getStyleClass().remove(PROXY_LIST_ITEM_SELECT_CLASS);
|
||||
}
|
||||
@ -383,30 +394,31 @@ public class MainController extends BaseController<StackPane> implements Initial
|
||||
newValue.getStyleClass().add(PROXY_LIST_ITEM_SELECT_CLASS);
|
||||
int oldIndex = items.indexOf(oldValue);
|
||||
int newIndex = items.indexOf(newValue);
|
||||
if (oldIndex != -1) proxyList.set(oldIndex, proxySetupModel.get());
|
||||
// 保存隧道状态
|
||||
ObservableList<ProxySetup> proxyList = proxyList();
|
||||
if (oldIndex != -1 && StringUtils.isNotEmpty(proxyList.get(oldIndex).getProxy_name()))
|
||||
proxyList.set(oldIndex, proxySetupModel.get());
|
||||
proxySetup = proxyList.get(newIndex);
|
||||
selectProxy.set(newIndex);
|
||||
selectProxy(newIndex);
|
||||
Platform.runLater(() -> {
|
||||
setting.set(false);
|
||||
setup.set(false);
|
||||
proxySetupModel.set(proxySetup);
|
||||
FrpUtil frpUtil = frpUtilMap.get(proxySetup.getProxy_name());
|
||||
proxyLogPane.contentProperty().set(frpUtil == null ? null : frpUtil.getConsole());
|
||||
setting.set(true);
|
||||
FrpManager frpManager = frpUtilMap.get(proxySetup.getProxy_name());
|
||||
proxyLogPane.contentProperty().set(frpManager == null ? null : frpManager.getConsole());
|
||||
setup.set(true);
|
||||
setDomainLink();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 添加隧道
|
||||
addProxyBtn.setOnMouseClicked(event -> {
|
||||
// 保存运行状态
|
||||
proxyList.get(selectProxy.get()).setRuning(proxySetupModel.isRunning());
|
||||
// 获取默认隧道设置
|
||||
proxySetup = ProxyUtil.initProxy(proxyList.get(proxyList.size() - 1).getSort());
|
||||
// 加入列表
|
||||
proxyList.add(proxySetup);
|
||||
initProxyList(proxyList);
|
||||
// 展示
|
||||
proxyListView.getSelectionModel().select(proxyList.size() - 1);
|
||||
// 获取默认隧道设置加入列表
|
||||
ObservableList<ProxySetup> proxyList = proxyList();
|
||||
addProxyList(ProxyManager.initProxy(proxyList.get(proxyList.size() - 1).getSort()));
|
||||
// 重置隧道列表视图
|
||||
initProxyListView();
|
||||
proxyListView.getSelectionModel().select(proxyListView.getItems().size() - 1);
|
||||
});
|
||||
|
||||
// 启动
|
||||
@ -433,27 +445,28 @@ public class MainController extends BaseController<StackPane> implements Initial
|
||||
// 复制成功提示
|
||||
AlertUtil.info("复制成功,快去分享给小伙伴吧!").show();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示隧道列表
|
||||
*/
|
||||
private void initProxyList(List<ProxySetup> proxyList) {
|
||||
// 清空列表
|
||||
proxyListView.getItems().clear();
|
||||
|
||||
for (ProxySetup proxy : proxyList) {
|
||||
// 退出登录
|
||||
logoutBtn.setOnMouseClicked(event -> {
|
||||
for (String key : frpUtilMap.keySet()) {
|
||||
frpUtilMap.get(key).stop();
|
||||
}
|
||||
ApplicatonStore.logout();
|
||||
try {
|
||||
Label label = FXMLLoader.load(getClass().getResource("/fxml/proxyItem.fxml"));
|
||||
label.textProperty().set(proxy.getProxy_name());
|
||||
ObservableList<String> styleClass = label.getStyleClass();
|
||||
styleClass.addAll(PROXY_LIST_ITEM_CLASS, proxy.isRuning() ? PROXY_LIST_ITEM_RUN_CLASS : PROXY_LIST_ITEM_STOP_CLASS);
|
||||
proxyListView.getItems().add(label);
|
||||
jumpTo(new LoginController());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
//
|
||||
// private void initEmptyProxyListView() {
|
||||
// // 初始化视图模型
|
||||
// proxySetup = ProxyManager.initProxy(null);
|
||||
// proxySetupModel = new ProxySetupModel(proxySetup);
|
||||
// setProxyList(Collections.singletonList(proxySetup));
|
||||
// initProxyListView();
|
||||
// }
|
||||
|
||||
/**
|
||||
* 是否启用当前隧道
|
||||
@ -468,7 +481,7 @@ public class MainController extends BaseController<StackPane> implements Initial
|
||||
domainTextField.setDisable(close); // 外网子域名
|
||||
startProxyBtn.setDisable(close); // 启动按钮
|
||||
|
||||
ObservableList<String> styleClass = proxyListView.getItems().get(selectProxy.get()).getStyleClass();
|
||||
ObservableList<String> styleClass = proxyListView.getItems().get(selectProxy()).getStyleClass();
|
||||
styleClass.remove(PROXY_LIST_ITEM_STOP_CLASS);
|
||||
styleClass.remove(PROXY_LIST_ITEM_RUN_CLASS);
|
||||
styleClass.remove(PROXY_LIST_ITEM_CLOSE_CLASS);
|
||||
@ -479,25 +492,73 @@ public class MainController extends BaseController<StackPane> implements Initial
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO 启动代理
|
||||
*/
|
||||
private void startProxy() {
|
||||
// 非 http 隧道系统随机分配端口
|
||||
if (!DomainUtil.isHttp(proxySetupModel)) {
|
||||
proxySetupModel.setRemotePort(String.valueOf(ProxyUtil.randomPort()));
|
||||
private void initProxyListView() {
|
||||
ObservableList<ProxySetup> proxyList = proxyList();
|
||||
for (ProxySetup proxy : proxyList.subList(proxyListView.getItems().size(), proxyList.size())) {
|
||||
setProxyListView(proxyList.indexOf(proxy), proxy);
|
||||
}
|
||||
// 设置选中
|
||||
proxyListView.getSelectionModel().select(selectProxy());
|
||||
}
|
||||
|
||||
private void setProxyListView(int index, ProxySetup setup) {
|
||||
ObservableList<Label> items = proxyListView.getItems();
|
||||
try {
|
||||
Label label = FXMLLoader.load(getClass().getResource("/fxml/proxyItem.fxml"));
|
||||
label.textProperty().set(setup.getProxy_name());
|
||||
ObservableList<String> styleClass = label.getStyleClass();
|
||||
styleClass.addAll(PROXY_LIST_ITEM_CLASS, setup.isRuning() ? PROXY_LIST_ITEM_RUN_CLASS : PROXY_LIST_ITEM_STOP_CLASS);
|
||||
if (index < items.size()) {
|
||||
items.set(index, label);
|
||||
} else {
|
||||
items.add(label);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
proxyListView.getSelectionModel().select(items.size() - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动代理
|
||||
*/
|
||||
private void startProxy() {
|
||||
// 验证
|
||||
if(!domainTextField.validate() || !localHostTextField.validate() || !localPortTextField.validate())
|
||||
return;
|
||||
|
||||
// 非 http 隧道系统随机分配端口
|
||||
if (!DomainUtil.isHttp(proxySetupModel)) {
|
||||
proxySetupModel.setRemotePort(String.valueOf(ProxyManager.randomPort()));
|
||||
}
|
||||
|
||||
// 是用户隧道
|
||||
if (proxySetupModel.getId() != null && !proxySetupModel.get().equals(proxySetup)) {
|
||||
// 删除旧隧道
|
||||
ProxyUtil.delete(proxySetupModel.getId());
|
||||
ProxyManager.delete(Integer.parseInt(proxySetupModel.getId()));
|
||||
|
||||
// 添加隧道
|
||||
ProxyUtil.add(new OnHttpListener<ProxySetup>() {
|
||||
ProxyManager.add(new OnHttpListener<ProxySetup>() {
|
||||
@Override
|
||||
public void onSucceed(ProxySetup result) {
|
||||
proxySetup = result;
|
||||
proxySetupModel.set(proxySetup);
|
||||
result.setRuning(frpUtilMap.containsKey(result.getProxy_name()));
|
||||
proxySetupModel.set(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFail(Exception e) {
|
||||
|
||||
}
|
||||
}, proxySetupModel.get());
|
||||
} else if(proxySetupModel.getId() == null) {
|
||||
|
||||
// 添加隧道
|
||||
ProxyManager.add(new OnHttpListener<ProxySetup>() {
|
||||
@Override
|
||||
public void onSucceed(ProxySetup result) {
|
||||
result.setRuning(frpUtilMap.containsKey(result.getProxy_name()));
|
||||
proxySetupModel.set(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -508,23 +569,33 @@ public class MainController extends BaseController<StackPane> implements Initial
|
||||
}
|
||||
|
||||
// 初始化frputil
|
||||
FrpUtil frpUtil;
|
||||
if ((frpUtil = frpUtilMap.get(proxySetupModel.getProxyName())) == null)
|
||||
frpUtilMap.put(proxySetupModel.getProxyName(), frpUtil = FrpUtil.init(proxySetupModel));
|
||||
FrpManager frpManager;
|
||||
if ((frpManager = frpUtilMap.get(proxySetupModel.getProxyName())) == null)
|
||||
frpUtilMap.put(proxySetupModel.getProxyName(), frpManager = FrpManager.init(proxySetupModel));
|
||||
|
||||
// 设置文本域对象
|
||||
if (proxyLogPane.getContent() == null) proxyLogPane.contentProperty().set(frpUtil.getConsole());
|
||||
if (proxyLogPane.getContent() == null) proxyLogPane.contentProperty().set(frpManager.getConsole());
|
||||
|
||||
// 开始
|
||||
frpUtil.start();
|
||||
frpManager.start();
|
||||
|
||||
// 显示日志
|
||||
tabPane.getSelectionModel().select(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO 暂停代理
|
||||
* 暂停代理
|
||||
*/
|
||||
private void stopProxy() {
|
||||
// 关闭CMD
|
||||
FrpUtil frpUtil = frpUtilMap.get(proxySetupModel.getProxyName());
|
||||
if (frpUtil != null) frpUtil.stop();
|
||||
FrpManager frpManager = frpUtilMap.get(proxySetupModel.getProxyName());
|
||||
if (frpManager != null) frpManager.stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
|
||||
|
||||
super.onDestroy();
|
||||
}
|
||||
}
|
||||
|
@ -10,15 +10,15 @@ import javafx.scene.layout.StackPane;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import top.octopusyan.base.BaseController;
|
||||
import top.octopusyan.manager.http.EasyHttp;
|
||||
import top.octopusyan.manager.http.listener.OnHttpListener;
|
||||
import top.octopusyan.config.TextValidate;
|
||||
import top.octopusyan.http.Api;
|
||||
import top.octopusyan.http.request.RegisterParam;
|
||||
import top.octopusyan.http.request.SendEmailCheckParam;
|
||||
import top.octopusyan.manager.http.EasyHttp;
|
||||
import top.octopusyan.manager.http.listener.OnHttpListener;
|
||||
import top.octopusyan.model.ApplicatonStore;
|
||||
import top.octopusyan.utils.AlertUtil;
|
||||
import top.octopusyan.utils.ApplicatonStore;
|
||||
import top.octopusyan.utils.JsoupUtil;
|
||||
import top.octopusyan.config.TextValidate;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
@ -180,7 +180,7 @@ public class RegisterController extends BaseController<StackPane> implements Ser
|
||||
if (JsoupUtil.isAlertSuccess(result)) {
|
||||
// 注册成功
|
||||
Platform.runLater(() ->
|
||||
AlertUtil.info(JsoupUtil.getHtmlMessage(result)).header(null).show()
|
||||
AlertUtil.info(JsoupUtil.getSuccessMessage(result)).header(null).show()
|
||||
);
|
||||
ApplicatonStore.setRegisterSuccess(true);
|
||||
Platform.runLater(() -> {
|
||||
|
@ -1,15 +1,12 @@
|
||||
package top.octopusyan.http;
|
||||
|
||||
import top.octopusyan.http.request.*;
|
||||
import top.octopusyan.manager.http.api.NotParamApi;
|
||||
import top.octopusyan.manager.http.api.ParamApi;
|
||||
import top.octopusyan.manager.http.api.PathParamApi;
|
||||
import top.octopusyan.manager.http.config.BodyType;
|
||||
import top.octopusyan.manager.http.config.HttpConstant;
|
||||
import top.octopusyan.http.request.ProxySetup;
|
||||
import top.octopusyan.http.request.RegisterParam;
|
||||
import top.octopusyan.http.request.SendEmailCheckParam;
|
||||
import top.octopusyan.http.request.LoginParam;
|
||||
import top.octopusyan.utils.ProxyUtil;
|
||||
import top.octopusyan.manager.ProxyManager;
|
||||
|
||||
/**
|
||||
* @author : octopus yan
|
||||
@ -39,12 +36,21 @@ public class Api {
|
||||
BodyType.FORM
|
||||
);
|
||||
|
||||
/** 获取服务器配置 */
|
||||
public static final PathParamApi<String> ServerConfiguration = new PathParamApi<>(
|
||||
"/?page=panel&module=configuration&server={0}",
|
||||
HttpConstant.Method.GET
|
||||
/** 找回密码 */
|
||||
public static ParamApi<FindPassParam, String> findpass = new ParamApi<>(
|
||||
"/?action=findpass&page=findpass",
|
||||
HttpConstant.Method.POST,
|
||||
BodyType.FORM
|
||||
);
|
||||
|
||||
/** 获取服务器配置 */
|
||||
public static PathParamApi<String> getServerConfiguration(int node){
|
||||
return new PathParamApi<>(
|
||||
"/?page=panel&module=configuration&server="+node,
|
||||
HttpConstant.Method.GET
|
||||
);
|
||||
}
|
||||
|
||||
/** 隧道列表 */
|
||||
public static final NotParamApi<String> ProxyList = new NotParamApi<>(
|
||||
"/?page=panel&module=proxies",
|
||||
@ -54,7 +60,7 @@ public class Api {
|
||||
/** 隧道详情 */
|
||||
public static PathParamApi<String> ProxyInfo() {
|
||||
return new PathParamApi<>(
|
||||
"/?page=panel&module=proxies&getproxyinfo={0}&csrf=" + ProxyUtil.getCsrf(),
|
||||
"/?page=panel&module=proxies&getproxyinfo={0}&csrf=" + ProxyManager.getCsrf(),
|
||||
HttpConstant.Method.GET
|
||||
);
|
||||
}
|
||||
@ -62,7 +68,7 @@ public class Api {
|
||||
/** 添加隧道 */
|
||||
public static ParamApi<ProxySetup, String> AddProxy() {
|
||||
return new ParamApi<>(
|
||||
"/?page=panel&module=addproxy&action=addproxy&csrf=" + ProxyUtil.getCsrf(),
|
||||
"/?page=panel&module=addproxy&action=addproxy&csrf=" + ProxyManager.getCsrf(),
|
||||
HttpConstant.Method.POST,
|
||||
BodyType.FORM
|
||||
);
|
||||
@ -71,7 +77,7 @@ public class Api {
|
||||
/** 删除隧道 */
|
||||
public static PathParamApi<Void> DeleteProxy() {
|
||||
return new PathParamApi<>(
|
||||
"/?page=panel&module=proxies&delete={0}&csrf=" + ProxyUtil.getCsrf(),
|
||||
"/?page=panel&module=proxies&delete={0}&csrf=" + ProxyManager.getCsrf(),
|
||||
HttpConstant.Method.GET
|
||||
);
|
||||
}
|
||||
@ -79,7 +85,7 @@ public class Api {
|
||||
/** 随机端口 */
|
||||
public static NotParamApi<String> RandomPort() {
|
||||
return new NotParamApi<>(
|
||||
"/?page=panel&module=addproxy&randomport&csrf=" + ProxyUtil.getCsrf(),
|
||||
"/?page=panel&module=addproxy&randomport&csrf=" + ProxyManager.getCsrf(),
|
||||
HttpConstant.Method.GET
|
||||
);
|
||||
}
|
||||
|
16
src/main/java/top/octopusyan/http/request/FindPassParam.java
Normal file
16
src/main/java/top/octopusyan/http/request/FindPassParam.java
Normal file
@ -0,0 +1,16 @@
|
||||
package top.octopusyan.http.request;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* <p> author : octopus yan
|
||||
* <p> email : octopus_yan@foxmail.com
|
||||
* <p> description : 找回密码请求参数
|
||||
* <p> create : 2022-4-10 20:20 *
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class FindPassParam {
|
||||
private String username;
|
||||
}
|
@ -28,8 +28,10 @@ public class ProxySetup {
|
||||
private String host_header_rewrite;
|
||||
private String header_X_From_Where;
|
||||
private String sk;
|
||||
private Integer sort;
|
||||
|
||||
// 非保留数据
|
||||
/** 是否启用 */
|
||||
private Boolean status;
|
||||
private Integer sort;
|
||||
private boolean runing;
|
||||
}
|
||||
|
@ -1,91 +1,59 @@
|
||||
package top.octopusyan.utils;
|
||||
package top.octopusyan.manager;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import javafx.scene.control.TextArea;
|
||||
import lombok.Data;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import top.octopusyan.manager.ThreadPoolManager;
|
||||
import top.octopusyan.model.ApplicatonStore;
|
||||
import top.octopusyan.model.ProxySetupModel;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author : octopus yan
|
||||
* @email : octopus_yan@foxmail.com
|
||||
* @description : TODO frp 工具
|
||||
* @description : frp 客户端 工具
|
||||
* @create : 2022-4-7 23:19
|
||||
*/
|
||||
public class FrpUtil {
|
||||
public class FrpManager {
|
||||
public static List<FrpManager> frpcList = new ArrayList<>();
|
||||
private static final String YAN_FRP_TEMP_DIR_NAME = "frpclienttmp";
|
||||
private static final String FRPC_CLIENT_FILE_NAME = "frpclienttmpfile.exe";
|
||||
public static final String FRPC_CLIENT_FILE_NAME = "frpclienttmpfile.exe";
|
||||
private final String FRPC_CONF_PREFIX_NAME = "proxy_";
|
||||
private final String FRPC_CONF_SUFFIX_NAME = ".ini";
|
||||
/**
|
||||
* 应用临时目录 地址
|
||||
*/
|
||||
private static final String YAN_FRP_TEMP_DIR_PATH = System.getProperty("java.io.tmpdir") + System.currentTimeMillis() + YAN_FRP_TEMP_DIR_NAME;
|
||||
private static final String FRPC_CLIENT_FILE_PATH = YAN_FRP_TEMP_DIR_PATH + File.separator + FRPC_CLIENT_FILE_NAME;
|
||||
private static final File frpcDir = new File(YAN_FRP_TEMP_DIR_PATH);
|
||||
/**
|
||||
* frpc 地址
|
||||
*/
|
||||
private static final String FRPC_CLIENT_FILE_PATH = ApplicatonStore.appDataDirPath + File.separator + FRPC_CLIENT_FILE_NAME;
|
||||
private static final File frpconfigDir = new File(YAN_FRP_TEMP_DIR_PATH);
|
||||
public static final File frpc = new File(FRPC_CLIENT_FILE_PATH);
|
||||
public File frpcConfigFile;
|
||||
|
||||
private final ProxySetupModel model;
|
||||
private final TextArea console;
|
||||
private Thread thread;
|
||||
private ProxyThread thread;
|
||||
private Process exec;
|
||||
|
||||
|
||||
private FrpUtil(TextArea console, ProxySetupModel model) {
|
||||
private FrpManager(TextArea console, ProxySetupModel model) {
|
||||
this.console = console;
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
public static FrpUtil init(ProxySetupModel model) {
|
||||
public static FrpManager init(ProxySetupModel model) {
|
||||
TextArea console = new TextArea();
|
||||
console.setPrefHeight(180);
|
||||
console.setMinWidth(200);
|
||||
return new FrpUtil(console, model);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化frpc客户端文件
|
||||
*/
|
||||
public static void initFrpc() throws IOException {
|
||||
|
||||
// 存在就删除
|
||||
if (frpcDir.exists()) FrpUtil.clearTmp();
|
||||
|
||||
// 重新创建
|
||||
frpcDir.mkdir();
|
||||
frpc.createNewFile();
|
||||
|
||||
// 发送删除请求
|
||||
frpcDir.deleteOnExit();
|
||||
frpc.deleteOnExit();
|
||||
|
||||
// 复制 frpc
|
||||
String fprcFilePath = FrpUtil.class.getResource("/static/frpc.exe").getFile();
|
||||
System.out.println(fprcFilePath);
|
||||
copyFileUsingFileStreams(FrpUtil.class.getResourceAsStream("/static/frpc.exe"), frpc);
|
||||
// FileUtils.copyFile(new File(fprcFilePath), frpc);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理缓存
|
||||
*/
|
||||
public static void clearTmp() {
|
||||
try {
|
||||
FileUtils.deleteDirectory(frpcDir);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
try {
|
||||
Runtime.getRuntime().exec("taskkill /im " + FRPC_CLIENT_FILE_NAME + " /f");
|
||||
Thread.sleep(2000);
|
||||
FileUtils.deleteDirectory(frpcDir);
|
||||
} catch (InterruptedException | IOException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
FrpManager frpManager = new FrpManager(console, model);
|
||||
frpcList.add(frpManager);
|
||||
return frpManager;
|
||||
}
|
||||
|
||||
public TextArea getConsole() {
|
||||
@ -96,43 +64,7 @@ public class FrpUtil {
|
||||
* 开始
|
||||
*/
|
||||
public void start() {
|
||||
|
||||
thread = new Thread(() -> {
|
||||
|
||||
Platform.runLater(() -> console.appendText("yan-frp-info:正在启动\n"));
|
||||
try {
|
||||
// 检查客户端文件
|
||||
if (!frpc.exists()) initFrpc();
|
||||
|
||||
// 初始化配置文件
|
||||
initProxyConfigFile();
|
||||
|
||||
// 执行命令
|
||||
String command = FRPC_CLIENT_FILE_PATH + " -c " + getConfigFilePath();
|
||||
System.out.println(command);
|
||||
exec = Runtime.getRuntime().exec(command, null, frpcDir);
|
||||
|
||||
// 设置运行状态
|
||||
Platform.runLater(() -> model.setRunning(true));
|
||||
|
||||
// 获取标准输出
|
||||
BufferedReader readStdout = new BufferedReader(new InputStreamReader(exec.getInputStream()));
|
||||
|
||||
// 逐行读取
|
||||
String line;
|
||||
while ((line = readStdout.readLine()) != null) {
|
||||
String finalLine = line;
|
||||
Platform.runLater(() -> console.appendText("yan-frp-info:" + finalLine + "\n"));
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
//
|
||||
Platform.runLater(() -> console.appendText("yan-frp-error:" + e.getMessage() + "\n"));
|
||||
Platform.runLater(() -> console.appendText("yan-frp-error:启动失败\n"));
|
||||
}
|
||||
});
|
||||
|
||||
thread = new ProxyThread();
|
||||
thread.start();
|
||||
}
|
||||
|
||||
@ -145,7 +77,7 @@ public class FrpUtil {
|
||||
do {
|
||||
if (exec != null && exec.isAlive())
|
||||
exec.destroy();
|
||||
|
||||
thread.setExit(true);
|
||||
thread.interrupt();
|
||||
|
||||
} while (!thread.isInterrupted());
|
||||
@ -182,18 +114,62 @@ public class FrpUtil {
|
||||
private void initProxyConfigFile() throws IOException {
|
||||
// 创建配置文件
|
||||
frpcConfigFile = new File(getConfigFilePath());
|
||||
if (frpcConfigFile.exists()) {
|
||||
frpcConfigFile.delete();
|
||||
if (!frpcConfigFile.exists()) {
|
||||
FileUtils.createParentDirectories(frpcConfigFile);
|
||||
frpcConfigFile.createNewFile();
|
||||
}
|
||||
frpcConfigFile.createNewFile();
|
||||
frpcConfigFile.deleteOnExit();
|
||||
|
||||
// 写入服务配置
|
||||
FileUtils.write(frpcConfigFile, ProxyUtil.getUserServerConfig(model.get().getNode()), StandardCharsets.UTF_8);
|
||||
FileUtils.write(frpcConfigFile, ProxyManager.getUserServerConfig(model.get().getNode()), StandardCharsets.UTF_8);
|
||||
// 写入隧道配置
|
||||
FileUtils.write(frpcConfigFile, ProxyUtil.getProxyConfig(model), StandardCharsets.UTF_8, true);
|
||||
FileUtils.write(frpcConfigFile, ProxyManager.getProxyConfig(model), StandardCharsets.UTF_8, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化frpc客户端文件
|
||||
*/
|
||||
public static void initFrpc() throws IOException {
|
||||
// frpc 文件
|
||||
if (!frpc.exists()) {
|
||||
frpc.createNewFile();
|
||||
|
||||
// 复制 frpc
|
||||
copyFileUsingFileStreams(FrpManager.class.getResourceAsStream("/static/frpc.exe"), frpc);
|
||||
}
|
||||
|
||||
// frpc 临时配置文件
|
||||
// 存在就删除
|
||||
if (frpconfigDir.exists()) FrpManager.clearTmp();
|
||||
// 重新创建
|
||||
frpconfigDir.mkdir();
|
||||
// 发送删除请求
|
||||
frpconfigDir.deleteOnExit();
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理缓存
|
||||
*/
|
||||
public static void clearTmp() {
|
||||
try {
|
||||
FileUtils.deleteDirectory(frpconfigDir);
|
||||
|
||||
for (File file : FileUtils.getTempDirectory().listFiles()) {
|
||||
if (file.getPath().contains(YAN_FRP_TEMP_DIR_NAME) && file.canWrite() && file.isDirectory()) {
|
||||
FileUtils.deleteDirectory(file);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
try {
|
||||
Runtime.getRuntime().exec("taskkill /im " + FRPC_CLIENT_FILE_NAME + " /f");
|
||||
Thread.sleep(1000);
|
||||
FileUtils.deleteDirectory(frpconfigDir);
|
||||
} catch (InterruptedException | IOException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void copyFileUsingFileStreams(InputStream input, File dest)
|
||||
throws IOException {
|
||||
@ -210,4 +186,46 @@ public class FrpUtil {
|
||||
output.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Data
|
||||
class ProxyThread extends Thread{
|
||||
private volatile boolean exit = false;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Platform.runLater(() -> console.appendText("yan-frp-info:正在启动\n"));
|
||||
try {
|
||||
// 检查客户端文件
|
||||
if (!frpc.exists()) initFrpc();
|
||||
|
||||
// 初始化配置文件
|
||||
initProxyConfigFile();
|
||||
|
||||
// 执行命令
|
||||
String command = FRPC_CLIENT_FILE_PATH + " -c " + getConfigFilePath();
|
||||
System.out.println(command);
|
||||
exec = Runtime.getRuntime().exec(command, null, frpconfigDir);
|
||||
|
||||
// 设置运行状态
|
||||
Platform.runLater(() -> model.setRunning(true));
|
||||
|
||||
// 获取标准输出
|
||||
BufferedReader readStdout = new BufferedReader(new InputStreamReader(exec.getInputStream()));
|
||||
|
||||
// 逐行读取
|
||||
String line;
|
||||
while ((line = readStdout.readLine()) != null && !exit) {
|
||||
String finalLine = line;
|
||||
System.out.println("yan-frp-info:" + line);
|
||||
Platform.runLater(() -> console.appendText("yan-frp-info:" + finalLine + "\n"));
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
//
|
||||
Platform.runLater(() -> console.appendText("yan-frp-error:" + e.getMessage() + "\n"));
|
||||
Platform.runLater(() -> console.appendText("yan-frp-error:启动失败\n"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,19 +1,22 @@
|
||||
package top.octopusyan.utils;
|
||||
package top.octopusyan.manager;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.nodes.Document;
|
||||
import org.jsoup.select.Elements;
|
||||
import top.octopusyan.manager.http.EasyHttp;
|
||||
import top.octopusyan.manager.http.listener.OnHttpListener;
|
||||
import top.octopusyan.manager.http.model.ResponseClass;
|
||||
import top.octopusyan.config.ProxyConfig;
|
||||
import top.octopusyan.config.ProxyConfig.ProxyServer;
|
||||
import top.octopusyan.config.ProxyConfig.ProxyType;
|
||||
import top.octopusyan.http.Api;
|
||||
import top.octopusyan.http.request.ProxySetup;
|
||||
import top.octopusyan.manager.http.EasyHttp;
|
||||
import top.octopusyan.manager.http.listener.OnHttpListener;
|
||||
import top.octopusyan.manager.http.model.ResponseClass;
|
||||
import top.octopusyan.model.ApplicatonStore;
|
||||
import top.octopusyan.model.ProxySetupModel;
|
||||
import top.octopusyan.utils.AlertUtil;
|
||||
import top.octopusyan.utils.JsoupUtil;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@ -27,7 +30,7 @@ import java.util.stream.Collectors;
|
||||
* @description : 代理设置工具
|
||||
* @create : 2022-4-5 09:56
|
||||
*/
|
||||
public class ProxyUtil {
|
||||
public class ProxyManager {
|
||||
private static String csrf;
|
||||
private static Map<Integer, String> serverConfigraution = new HashMap<>(3);
|
||||
|
||||
@ -173,8 +176,9 @@ public class ProxyUtil {
|
||||
|
||||
if (result != null && result.size() > 0) {
|
||||
for (ProxySetup proxySetup : result) {
|
||||
if (Objects.equals(proxySetup.getSort(), proxySetup.getSort())) {
|
||||
if (Objects.equals(proxySetup.getSort(), setup.getSort())) {
|
||||
listener.onSucceed(proxySetup);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -201,7 +205,7 @@ public class ProxyUtil {
|
||||
public static void setCsrf(String htmlStr) {
|
||||
int i = htmlStr.indexOf("var csrf_token = \"");
|
||||
int i1 = htmlStr.indexOf("\"", i + 18);
|
||||
ProxyUtil.csrf = htmlStr.substring(i + 18, i1);
|
||||
ProxyManager.csrf = htmlStr.substring(i + 18, i1);
|
||||
}
|
||||
|
||||
public static String getUserServerConfig(int node) {
|
||||
@ -209,7 +213,7 @@ public class ProxyUtil {
|
||||
if (StringUtils.isNotEmpty(config)) return config;
|
||||
try {
|
||||
String result = EasyHttp.builder()
|
||||
.api(Api.ServerConfiguration)
|
||||
.api(Api.getServerConfiguration(node))
|
||||
.pathParam(String.valueOf(node))
|
||||
.execute(new ResponseClass<String>() {
|
||||
});
|
||||
@ -225,31 +229,31 @@ public class ProxyUtil {
|
||||
public static String getProxyConfig(ProxySetupModel setup) {
|
||||
String n = "\n";
|
||||
// 基础配置
|
||||
StringBuffer stringBuffer = new StringBuffer("[" + setup.getProxyName() + "]\n");
|
||||
stringBuffer.append("privilege_mode = true\n")
|
||||
.append("type = ").append(setup.getProxyType()).append(n)
|
||||
StringBuilder stringBuilder = new StringBuilder("[" + ApplicatonStore.getAccount() + "_" + setup.getProxyName() + "]\n");
|
||||
stringBuilder.append("privilege_mode = true\n")
|
||||
.append("type = ").append(setup.getProxyType().contains("http") ? "http" : setup.getProxyType()).append(n)
|
||||
.append("local_ip = ").append(setup.getLocalIp()).append(n)
|
||||
.append("local_port = ").append(setup.getLocalPort()).append(n).append(n);
|
||||
|
||||
if ("http".equals(setup.getProxyType()) || "https".equals(setup.getProxyType())) {
|
||||
// HTTP / HTTPS
|
||||
stringBuffer.append("custom_domains = ").append(setup.getDomain()).append(setup.getDomainSuffix()).append(n);
|
||||
stringBuilder.append("custom_domains = ").append(setup.getDomain()).append(setup.getDomainSuffix()).append(n);
|
||||
if (!StringUtils.isEmpty(setup.getLocations()))
|
||||
stringBuffer.append("locations = ").append(setup.getLocations()).append(n);
|
||||
stringBuilder.append("locations = ").append(setup.getLocations()).append(n);
|
||||
if (!StringUtils.isEmpty(setup.getLocations()))
|
||||
stringBuffer.append("host_header_rewrite = ").append(setup.getHostHeaderRewrite()).append(n);
|
||||
stringBuilder.append("host_header_rewrite = ").append(setup.getHostHeaderRewrite()).append(n);
|
||||
if (!StringUtils.isEmpty(setup.getLocations()))
|
||||
stringBuffer.append("header_X-From-Where = ").append(setup.getHeader_X_From_Where()).append(n);
|
||||
stringBuilder.append("header_X-From-Where = ").append(setup.getHeader_X_From_Where()).append(n);
|
||||
} else {
|
||||
// TCP / UDP / XTCP / STCP
|
||||
stringBuffer.append("remote_port = ").append(setup.getRemotePort()).append(n);
|
||||
stringBuilder.append("remote_port = ").append(setup.getRemotePort()).append(n);
|
||||
if (!StringUtils.isEmpty(setup.getSk()))
|
||||
stringBuffer.append("sk = ").append(setup.getSk()).append(n);
|
||||
stringBuilder.append("sk = ").append(setup.getSk()).append(n);
|
||||
}
|
||||
// 压缩和加密
|
||||
stringBuffer.append("use_encryption = ").append(setup.isUseEncryption()).append(n)
|
||||
stringBuilder.append("use_encryption = ").append(setup.isUseEncryption()).append(n)
|
||||
.append("use_compression = ").append(setup.isUseCompression()).append(n).append(n);
|
||||
|
||||
return stringBuffer.toString();
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
}
|
@ -100,7 +100,7 @@ public interface ILogStrategy {
|
||||
* 创建对应数量的制表符
|
||||
*/
|
||||
static String getSpaceOrTab(int tabNum) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < tabNum; i++) {
|
||||
sb.append('\t');
|
||||
}
|
||||
|
222
src/main/java/top/octopusyan/model/ApplicatonStore.java
Normal file
222
src/main/java/top/octopusyan/model/ApplicatonStore.java
Normal file
@ -0,0 +1,222 @@
|
||||
package top.octopusyan.model;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.beans.property.SimpleIntegerProperty;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import top.octopusyan.http.request.ProxySetup;
|
||||
import top.octopusyan.utils.EncryptionUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author : octopus yan
|
||||
* @email : octopus_yan@foxmail.com
|
||||
* @description : 应用信息
|
||||
* @create : 2022-4-4 17:22
|
||||
*/
|
||||
public class ApplicatonStore {
|
||||
public static final String appDataDirPath = System.getProperty("user.home") + File.separator + "AppData" + File.separator + "Local" + File.separator + "yanfrp";
|
||||
public static final String appDataFilePath = appDataDirPath + File.separator + "yanfrp";
|
||||
private static final File appDataDir = new File(appDataDirPath);
|
||||
private static final File appDataFile = new File(appDataFilePath);
|
||||
private static final String ACCOUNT_KEY = "YANFRP_ACCOUNT";
|
||||
private static final String PASSWORD_KEY = "YANFRP_PASSWORD";
|
||||
private static final String AUTO_LOGIN_KEY = "YANFRP_AUTO_LOGIN";
|
||||
private static final String REMEMBER_ME_KEY = "YANFRP_REMEMBER_ME";
|
||||
private static final String SELECT_PROXY_NAME_KEY = "YANFRP_SELECT_PROXY_NAME";
|
||||
private static final SimpleStringProperty account = new SimpleStringProperty();
|
||||
private static final SimpleStringProperty password = new SimpleStringProperty();
|
||||
private static final SimpleStringProperty email = new SimpleStringProperty();
|
||||
private static final SimpleBooleanProperty autoLogin = new SimpleBooleanProperty();
|
||||
private static final SimpleBooleanProperty rememberMe = new SimpleBooleanProperty();
|
||||
private static final SimpleBooleanProperty registerSuccess = new SimpleBooleanProperty();
|
||||
private static final ObservableList<ProxySetup> proxyList = FXCollections.observableList(new ArrayList<>());
|
||||
private static final SimpleIntegerProperty selectProxy = new SimpleIntegerProperty(0);
|
||||
|
||||
public static void setAccount(String account) {
|
||||
ApplicatonStore.account.set(account);
|
||||
}
|
||||
|
||||
public static void setEmail(String email) {
|
||||
ApplicatonStore.email.set(email);
|
||||
}
|
||||
|
||||
public static void setPassword(String password) {
|
||||
ApplicatonStore.password.set(password);
|
||||
}
|
||||
|
||||
public static String getAccount() {
|
||||
return account.get();
|
||||
}
|
||||
|
||||
public static SimpleStringProperty accountProperty() {
|
||||
return account;
|
||||
}
|
||||
|
||||
public static String getEmail() {
|
||||
return email.get();
|
||||
}
|
||||
|
||||
public static String getPassword() {
|
||||
return password.get();
|
||||
}
|
||||
|
||||
public static SimpleStringProperty passwordProperty() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public static void setAutoLogin(boolean autoLogin) {
|
||||
ApplicatonStore.autoLogin.set(autoLogin);
|
||||
}
|
||||
|
||||
public static void setRememberMe(boolean rememberMe) {
|
||||
ApplicatonStore.rememberMe.set(rememberMe);
|
||||
}
|
||||
|
||||
public static boolean isAutoLogin() {
|
||||
return autoLogin.get();
|
||||
}
|
||||
|
||||
public static SimpleBooleanProperty autoLoginProperty() {
|
||||
return autoLogin;
|
||||
}
|
||||
|
||||
public static boolean isRememberMe() {
|
||||
return rememberMe.get();
|
||||
}
|
||||
|
||||
public static SimpleBooleanProperty rememberMeProperty() {
|
||||
return rememberMe;
|
||||
}
|
||||
|
||||
public static void setRegisterSuccess(boolean registerSuccess) {
|
||||
ApplicatonStore.registerSuccess.set(registerSuccess);
|
||||
}
|
||||
|
||||
public static boolean isRegisterSuccess() {
|
||||
return registerSuccess.get();
|
||||
}
|
||||
|
||||
public static ObservableList<ProxySetup> proxyList() {
|
||||
return proxyList;
|
||||
}
|
||||
|
||||
public static void setProxyList(List<ProxySetup> proxySetupList) {
|
||||
proxyList.setAll(proxySetupList);
|
||||
}
|
||||
|
||||
public static void addProxyList(ProxySetup proxySetup) {
|
||||
proxyList.add(proxySetup);
|
||||
}
|
||||
|
||||
public static void selectProxy(int selectProxy) {
|
||||
ApplicatonStore.selectProxy.set(selectProxy);
|
||||
}
|
||||
|
||||
public static int selectProxy() {
|
||||
return selectProxy.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化应用数据
|
||||
*/
|
||||
public static void init() {
|
||||
// 检查应用目录
|
||||
checkAppData();
|
||||
// 注册状态
|
||||
setRegisterSuccess(false);
|
||||
// 应用数据
|
||||
JSONObject appDataJson = new JSONObject();
|
||||
try {
|
||||
String str = FileUtils.readFileToString(appDataFile, StandardCharsets.UTF_8);
|
||||
appDataJson = JSON.parseObject(EncryptionUtil.decodeAppData(str));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (appDataJson == null) return;
|
||||
|
||||
// 账号
|
||||
if (appDataJson.containsKey(ACCOUNT_KEY)) account.set(appDataJson.getString(ACCOUNT_KEY));
|
||||
// 密码
|
||||
if (appDataJson.containsKey(PASSWORD_KEY)) password.set(appDataJson.getString(PASSWORD_KEY));
|
||||
// 自动登录
|
||||
if (appDataJson.containsKey(AUTO_LOGIN_KEY)) autoLogin.set(appDataJson.getBoolean(AUTO_LOGIN_KEY));
|
||||
// 记住
|
||||
if (appDataJson.containsKey(REMEMBER_ME_KEY)) rememberMe.set(appDataJson.getBoolean(REMEMBER_ME_KEY));
|
||||
// TODO 已选择隧道
|
||||
if (appDataJson.containsKey(SELECT_PROXY_NAME_KEY)) {
|
||||
// String proxtName = appDataJson.getString(SELECT_PROXY_NAME_KEY);
|
||||
// proxyListProperty().addListener(new );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 序列化应用信息到本地
|
||||
*/
|
||||
public static void save() {
|
||||
// 检查应用目录
|
||||
checkAppData();
|
||||
// 保存数据
|
||||
JSONObject appDataJson = new JSONObject();
|
||||
// 账号
|
||||
if (rememberMe.get() && account.get() != null) appDataJson.put(ACCOUNT_KEY, account.get());
|
||||
// 密码
|
||||
if (rememberMe.get() && password.get() != null) appDataJson.put(PASSWORD_KEY, password.get());
|
||||
// 选择隧道
|
||||
if (selectProxy.getValue() != null && proxyList.size() > 0 && proxyList.size() > selectProxy.get())
|
||||
appDataJson.put(SELECT_PROXY_NAME_KEY, proxyList.get(selectProxy.getValue()));
|
||||
// 自动登录
|
||||
appDataJson.put(AUTO_LOGIN_KEY, autoLogin.get());
|
||||
// 记住
|
||||
appDataJson.put(REMEMBER_ME_KEY, rememberMe.get());
|
||||
|
||||
try {
|
||||
String appDataStr = EncryptionUtil.encodeAppData(appDataJson.toJSONString());
|
||||
FileUtils.write(appDataFile, appDataStr, StandardCharsets.UTF_8);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void rememberMe(String password) {
|
||||
// 密码
|
||||
if (isRememberMe()) {
|
||||
setPassword(password);
|
||||
}
|
||||
}
|
||||
|
||||
public static void logout(){
|
||||
setRegisterSuccess(false);
|
||||
setAutoLogin(false);
|
||||
setRememberMe(false);
|
||||
setPassword("");
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查应用数据目录
|
||||
*/
|
||||
private static void checkAppData() {
|
||||
|
||||
// 应用目录
|
||||
if (!appDataDir.exists()) appDataDir.mkdirs();
|
||||
|
||||
// 应用数据文件
|
||||
if (!appDataFile.exists()) {
|
||||
try {
|
||||
appDataFile.createNewFile();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -15,7 +15,7 @@ import top.octopusyan.utils.DomainUtil;
|
||||
* @create : 2022-4-6 16:45
|
||||
*/
|
||||
public class ProxySetupModel {
|
||||
private final SimpleIntegerProperty id = new SimpleIntegerProperty();
|
||||
private final SimpleStringProperty id = new SimpleStringProperty();
|
||||
private final SimpleStringProperty server = new SimpleStringProperty();
|
||||
private final SimpleStringProperty proxyName = new SimpleStringProperty();
|
||||
private final SimpleStringProperty proxyType = new SimpleStringProperty();
|
||||
@ -36,6 +36,8 @@ public class ProxySetupModel {
|
||||
private final SimpleBooleanProperty isCustomize = new SimpleBooleanProperty();
|
||||
|
||||
public ProxySetupModel(ProxySetup setup) {
|
||||
if(setup == null) return;
|
||||
|
||||
String domainStr = setup.getDomain();
|
||||
String suffix = "";
|
||||
isCustomize.set(DomainUtil.isCustomize(setup));
|
||||
@ -57,13 +59,13 @@ public class ProxySetupModel {
|
||||
setUseCompression(setup.getUse_compression());
|
||||
setHeader_X_From_Where(setup.getHost_header_rewrite());
|
||||
setHostHeaderRewrite(setup.getHost_header_rewrite());
|
||||
setStatus(setup.getStatus());
|
||||
setStatus(setup.getStatus() == null || setup.getStatus());
|
||||
setSk(setup.getSk());
|
||||
setSort(setup.getSort());
|
||||
setRunning(setup.isRuning());
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
public String getId() {
|
||||
return id.get();
|
||||
}
|
||||
|
||||
@ -136,7 +138,7 @@ public class ProxySetupModel {
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
if(id != null) this.id.set(id);
|
||||
this.id.set(id == null ? null : id.toString());
|
||||
}
|
||||
|
||||
public void setProxyName(String proxyName) {
|
||||
@ -196,7 +198,7 @@ public class ProxySetupModel {
|
||||
}
|
||||
|
||||
public void setSort(Integer sort) {
|
||||
if(sort != null) this.sort.set(sort);
|
||||
if (sort != null) this.sort.set(sort);
|
||||
}
|
||||
|
||||
public void setStatus(boolean status) {
|
||||
@ -235,7 +237,7 @@ public class ProxySetupModel {
|
||||
return useEncryption;
|
||||
}
|
||||
|
||||
public SimpleIntegerProperty idProperty() {
|
||||
public SimpleStringProperty idProperty() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@ -292,7 +294,6 @@ public class ProxySetupModel {
|
||||
suffix = DomainUtil.getSuffix(setup);
|
||||
}
|
||||
setId(setup.getId());
|
||||
setServer(ProxyConfig.getServerName(setup.getNode()));
|
||||
setProxyName(setup.getProxy_name());
|
||||
setProxyType(setup.getProxy_type());
|
||||
setLocalIp(setup.getLocal_ip());
|
||||
@ -305,15 +306,17 @@ public class ProxySetupModel {
|
||||
setUseCompression(setup.getUse_compression());
|
||||
setHeader_X_From_Where(setup.getHost_header_rewrite());
|
||||
setHostHeaderRewrite(setup.getHost_header_rewrite());
|
||||
setStatus(setup.getStatus());
|
||||
setStatus(setup.getStatus() == null || setup.getStatus());
|
||||
setSk(setup.getSk());
|
||||
setSort(setup.getSort());
|
||||
setRunning(setup.isRuning());
|
||||
// 数据绑定原因 放在最后
|
||||
setServer(ProxyConfig.getServerName(setup.getNode()));
|
||||
}
|
||||
|
||||
public ProxySetup get() {
|
||||
return new ProxySetup(
|
||||
getId(),
|
||||
getId() == null ? null : Integer.parseInt(getId()),
|
||||
ProxyConfig.getServerNode(server.get()),
|
||||
getProxyName(),
|
||||
StringUtils.lowerCase(proxyType.getValue()),
|
||||
@ -327,8 +330,8 @@ public class ProxySetupModel {
|
||||
getHostHeaderRewrite(),
|
||||
getHeader_X_From_Where(),
|
||||
getSk(),
|
||||
getStatus(),
|
||||
getSort(),
|
||||
getStatus(),
|
||||
isRunning()
|
||||
);
|
||||
}
|
||||
|
@ -65,23 +65,32 @@ public class AlertUtil {
|
||||
alert.showAndWait();
|
||||
}
|
||||
|
||||
private void show(OnClickListener listener) {
|
||||
/**
|
||||
* AlertUtil.confirm
|
||||
* @param listener
|
||||
*/
|
||||
public void show(OnClickListener listener) {
|
||||
|
||||
Optional<ButtonType> result = alert.showAndWait();
|
||||
|
||||
listener.onClicked(result.get().getText());
|
||||
}
|
||||
|
||||
private void show(OnChoseListener listener) {
|
||||
/**
|
||||
* AlertUtil.confirm
|
||||
* @param listener
|
||||
*/
|
||||
public void show(OnChoseListener listener) {
|
||||
Optional<ButtonType> result = alert.showAndWait();
|
||||
if (result.get() == ButtonType.OK) {
|
||||
listener.confirm();
|
||||
} else {
|
||||
listener.cancelOrClose();
|
||||
listener.cancelOrClose(result.get());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* AlertUtil.input
|
||||
* 如果用户点击了取消按钮,将会返回null
|
||||
*/
|
||||
public String getInput() {
|
||||
@ -92,6 +101,12 @@ public class AlertUtil {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* AlertUtil.choices
|
||||
* @param choices
|
||||
* @param <R>
|
||||
* @return
|
||||
*/
|
||||
public <R> R getChoice(R... choices) {
|
||||
Optional<R> result = alert.showAndWait();
|
||||
return result.get();
|
||||
@ -155,6 +170,9 @@ public class AlertUtil {
|
||||
return alert;
|
||||
}
|
||||
|
||||
/**
|
||||
* 确认对话框
|
||||
*/
|
||||
public static Builder confirm() {
|
||||
Alert alert = new Alert(AlertType.CONFIRMATION);
|
||||
alert.setTitle("确认对话框");
|
||||
@ -196,7 +214,7 @@ public class AlertUtil {
|
||||
interface OnChoseListener {
|
||||
void confirm();
|
||||
|
||||
void cancelOrClose();
|
||||
void cancelOrClose(ButtonType buttonType);
|
||||
}
|
||||
|
||||
interface OnClickListener {
|
||||
|
@ -1,101 +0,0 @@
|
||||
package top.octopusyan.utils;
|
||||
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.beans.property.SimpleIntegerProperty;
|
||||
import javafx.beans.property.SimpleListProperty;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import top.octopusyan.http.request.ProxySetup;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author : octopus yan
|
||||
* @email : octopus_yan@foxmail.com
|
||||
* @description : 应用信息
|
||||
* @create : 2022-4-4 17:22
|
||||
*/
|
||||
public class ApplicatonStore {
|
||||
private static SimpleStringProperty account = new SimpleStringProperty();
|
||||
private static SimpleStringProperty password = new SimpleStringProperty();
|
||||
private static SimpleStringProperty email = new SimpleStringProperty();
|
||||
private static SimpleStringProperty sendMailCode = new SimpleStringProperty();
|
||||
private static SimpleBooleanProperty autoLogin = new SimpleBooleanProperty();
|
||||
private static SimpleBooleanProperty rememberMe = new SimpleBooleanProperty();
|
||||
private static SimpleBooleanProperty registerSuccess = new SimpleBooleanProperty();
|
||||
private static SimpleListProperty<ProxySetup> proxyList = new SimpleListProperty<>();
|
||||
private static SimpleIntegerProperty selectProxy = new SimpleIntegerProperty(0);
|
||||
|
||||
public static void setAccount(String account) {
|
||||
ApplicatonStore.account.set(account);
|
||||
}
|
||||
|
||||
public static void setEmail(String email) {
|
||||
ApplicatonStore.email.set(email);
|
||||
}
|
||||
|
||||
public static void setPassword(String password) {
|
||||
ApplicatonStore.password.set(password);
|
||||
}
|
||||
|
||||
public static void setSendMailCode(String sendMailCode) {
|
||||
ApplicatonStore.sendMailCode.set(sendMailCode);
|
||||
}
|
||||
|
||||
public static String getAccount() {
|
||||
return account.get();
|
||||
}
|
||||
|
||||
public static String getEmail() {
|
||||
return email.get();
|
||||
}
|
||||
|
||||
public static String getPassword() {
|
||||
return password.get();
|
||||
}
|
||||
|
||||
public static String getSendMailCode() {
|
||||
return sendMailCode.get();
|
||||
}
|
||||
|
||||
public static void setAutoLogin(boolean autoLogin) {
|
||||
ApplicatonStore.autoLogin.set(autoLogin);
|
||||
}
|
||||
|
||||
public static void setRememberMe(boolean rememberMe) {
|
||||
ApplicatonStore.rememberMe.set(rememberMe);
|
||||
}
|
||||
|
||||
public static boolean isAutoLogin() {
|
||||
return autoLogin.get();
|
||||
}
|
||||
|
||||
public static boolean isRememberMe() {
|
||||
return rememberMe.get();
|
||||
}
|
||||
|
||||
public static void setRegisterSuccess(boolean registerSuccess) {
|
||||
ApplicatonStore.registerSuccess.set(registerSuccess);
|
||||
}
|
||||
|
||||
public static boolean isRegisterSuccess() {
|
||||
return registerSuccess.get();
|
||||
}
|
||||
|
||||
public static ObservableList<ProxySetup> getProxyList() {
|
||||
return proxyList.get();
|
||||
}
|
||||
|
||||
public static void initProxyList(List<ProxySetup> proxySetupList) {
|
||||
ApplicatonStore.proxyList = new SimpleListProperty<>(FXCollections.observableList(proxySetupList));
|
||||
}
|
||||
|
||||
public static void setSelectProxy(int selectProxy) {
|
||||
ApplicatonStore.selectProxy.set(selectProxy);
|
||||
}
|
||||
|
||||
public static int getSelectProxy() {
|
||||
return selectProxy.get();
|
||||
}
|
||||
}
|
@ -1,13 +1,11 @@
|
||||
package top.octopusyan.utils;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import top.octopusyan.config.ProxyConfig;
|
||||
import top.octopusyan.http.request.ProxySetup;
|
||||
import top.octopusyan.model.ProxySetupModel;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author : octopus yan
|
||||
@ -34,10 +32,6 @@ public class DomainUtil {
|
||||
return ProxyConfig.getTypeIndex(model.getProxyType()) < 2;
|
||||
}
|
||||
|
||||
public static boolean isHttps(ProxySetupModel model){
|
||||
return ProxyConfig.getTypeIndex(model.getProxyType()) == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否自定义隧道
|
||||
*/
|
||||
|
@ -2,12 +2,11 @@ package top.octopusyan.utils;
|
||||
|
||||
import cn.hutool.core.codec.Base64;
|
||||
import cn.hutool.crypto.SecureUtil;
|
||||
import cn.hutool.crypto.digest.MD5;
|
||||
import sun.misc.BASE64Encoder;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import sun.misc.BASE64Encoder;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
@ -30,7 +29,7 @@ import java.util.Arrays;
|
||||
* @create : 2021-03-18 19:03
|
||||
*/
|
||||
public class EncryptionUtil {
|
||||
private static EncryptionUtil util;
|
||||
private static final String defaultPassword = "yanfrp";
|
||||
private static Logger logger = LoggerFactory.getLogger(EncryptionUtil.class);
|
||||
|
||||
private static BASE64Encoder BASE64Encoder;
|
||||
@ -51,7 +50,8 @@ public class EncryptionUtil {
|
||||
* 加解密算法/工作模式/填充方式
|
||||
*/
|
||||
private static final String ECB_MOB = "DES/ECB/PKCS5Padding";
|
||||
private static final String ALGORITHM_MODE_PADDING = "AES/ECB/PKCS7Padding";
|
||||
// private static final String ALGORITHM_MODE_PADDING = "AES/ECB/PKCS7Padding";
|
||||
private static final String ALGORITHM_MODE_PADDING = "AES/ECB/PKCS5Padding";
|
||||
|
||||
private static final Charset UTF_8 = StandardCharsets.UTF_8;
|
||||
|
||||
@ -60,20 +60,41 @@ public class EncryptionUtil {
|
||||
private static final char hexDigitsLower[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c',
|
||||
'd', 'e', 'f'};
|
||||
|
||||
public static synchronized EncryptionUtil getInstance() {
|
||||
if (util == null) {
|
||||
BASE64Encoder = new BASE64Encoder();
|
||||
try {
|
||||
MessageDigest_SHA1 = MessageDigest.getInstance("SHA-1");
|
||||
MessageDigest_MD5 = MessageDigest.getInstance("MD5");
|
||||
Cipher_ECB_MOB = Cipher.getInstance(ECB_MOB);
|
||||
Cipher_ALGORITHM_MODE_PADDING = Cipher.getInstance(ALGORITHM_MODE_PADDING);
|
||||
Signature_SHA256_RSA = Signature.getInstance("SHA256WithRSA");
|
||||
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
public static void init() {
|
||||
|
||||
BASE64Encoder = new BASE64Encoder();
|
||||
try {
|
||||
MessageDigest_SHA1 = MessageDigest.getInstance("SHA-1");
|
||||
MessageDigest_MD5 = MessageDigest.getInstance("MD5");
|
||||
Cipher_ECB_MOB = Cipher.getInstance(ECB_MOB);
|
||||
Cipher_ALGORITHM_MODE_PADDING = Cipher.getInstance(ALGORITHM_MODE_PADDING);
|
||||
Signature_SHA256_RSA = Signature.getInstance("SHA256WithRSA");
|
||||
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static String getDefaultPassword() {
|
||||
return getSHA(defaultPassword + getMessageDigestString("frp." + defaultPassword, hexDigits, MessageDigest_SHA1));
|
||||
}
|
||||
|
||||
public static String decodeAppData(String str){
|
||||
try {
|
||||
return DESdecode(str, getDefaultPassword());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static String encodeAppData(String str){
|
||||
try {
|
||||
return DESencode(str, getDefaultPassword());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
return util;
|
||||
}
|
||||
|
||||
public static String getSha1(String str) {
|
||||
|
@ -23,7 +23,7 @@ public class JsoupUtil {
|
||||
return getDocument(htmlStr).body().getElementsByClass("alert alert-danger alert-dismissable").text().substring(1);
|
||||
}
|
||||
|
||||
public static String getHtmlMessage(String htmlStr) {
|
||||
public static String getSuccessMessage(String htmlStr) {
|
||||
return getDocument(htmlStr).getElementsByClass("alert alert-success alert-dismissable").text().substring(1);
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,7 @@
|
||||
-fx-text-fill: #757575;
|
||||
}
|
||||
|
||||
/* TODO 隧道列表 */
|
||||
/* 隧道列表 */
|
||||
#proxyListView .list-cell:selected {
|
||||
-fx-background-color: linear-gradient(#9198e5, #57b4f2);
|
||||
}
|
||||
@ -93,7 +93,7 @@
|
||||
-fx-border-width: 0 1 1;
|
||||
-fx-font-size: 14px;
|
||||
-fx-text-fill: white;
|
||||
-fx-background-color: linear-gradient(rgba(87, 180, 242, 0.7), rgba(145, 152, 229, 0.71));
|
||||
-fx-background-color: linear-gradient(rgb(87, 180, 242), rgb(145, 152, 229));
|
||||
-fx-font-family: "Microsoft YaHei";
|
||||
}
|
||||
/* 启动 */
|
||||
|
@ -95,8 +95,8 @@
|
||||
<Font size="11.5"/>
|
||||
</font>
|
||||
</JFXCheckBox>
|
||||
<JFXButton alignment="TOP_CENTER" contentDisplay="RIGHT" prefHeight="23.0" prefWidth="64.0"
|
||||
text="找回密码" textAlignment="RIGHT" textFill="#00000078">
|
||||
<JFXButton fx:id="findpassBtn" alignment="TOP_CENTER" contentDisplay="RIGHT" prefHeight="23.0" prefWidth="64.0"
|
||||
text="忘记密码" textAlignment="RIGHT" textFill="#00000078">
|
||||
<font>
|
||||
<Font size="11.0"/>
|
||||
</font>
|
||||
|
@ -5,7 +5,6 @@
|
||||
<?import com.jfoenix.controls.JFXListView?>
|
||||
<?import com.jfoenix.controls.JFXRadioButton?>
|
||||
<?import com.jfoenix.controls.JFXTabPane?>
|
||||
<?import com.jfoenix.controls.JFXTextArea?>
|
||||
<?import com.jfoenix.controls.JFXTextField?>
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.Cursor?>
|
||||
@ -166,21 +165,24 @@
|
||||
<Insets right="20.0"/>
|
||||
</HBox.margin>
|
||||
</Label>
|
||||
<HBox prefWidth="320.0">
|
||||
<JFXTextField fx:id="domainTextField" alignment="CENTER" prefHeight="30.0" prefWidth="320.0"
|
||||
promptText="自定义子域名大于3位" styleClass="inputText-left">
|
||||
<AnchorPane maxHeight="30.0" prefHeight="30" prefWidth="320.0">
|
||||
<JFXTextField fx:id="domainTextField" prefHeight="31.0" prefWidth="320.0"
|
||||
promptText="自定义子域名大于3位" styleClass="inputText">
|
||||
<font>
|
||||
<Font size="14.0"/>
|
||||
</font>
|
||||
<padding>
|
||||
<Insets left="15.0"/>
|
||||
</padding>
|
||||
</JFXTextField>
|
||||
<JFXTextField fx:id="domainSuffixTextField" alignment="CENTER" disable="true"
|
||||
minWidth="155.0" prefHeight="30.0" styleClass="inputText-right"
|
||||
text=".frp.octopusyan.top">
|
||||
layoutX="165.0" prefHeight="30.0" prefWidth="155.0"
|
||||
styleClass="inputText-right" text=".frp.octopusyan.top">
|
||||
<font>
|
||||
<Font size="14.0"/>
|
||||
</font>
|
||||
</JFXTextField>
|
||||
</HBox>
|
||||
</AnchorPane>
|
||||
<JFXButton fx:id="customizeDomainBtn" prefHeight="Infinity" text="自定义">
|
||||
<HBox.margin>
|
||||
<Insets left="5.0"/>
|
||||
@ -227,15 +229,13 @@
|
||||
<AnchorPane prefHeight="Infinity" prefWidth="Infinity" GridPane.rowIndex="1">
|
||||
<JFXTabPane fx:id="tabPane" prefHeight="230" prefWidth="520.0" styleClass="mainPane">
|
||||
<tabs>
|
||||
<Tab fx:id="proxyLogPane" text=" 日志 ">
|
||||
<JFXTextArea prefWidth="Infinity"/>
|
||||
</Tab>
|
||||
<Tab fx:id="proxyLogPane" text=" 日志 "/>
|
||||
<Tab text="常见问题">
|
||||
<VBox minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
|
||||
<padding>
|
||||
<Insets left="20.0" top="20.0"/>
|
||||
</padding>
|
||||
<HBox prefHeight="30.0" prefWidth="Infinity">
|
||||
<HBox prefHeight="30.0" prefWidth="Infinity" visible="false">
|
||||
<Label prefHeight="Infinity" text="* 若启动后无法通过外网访问,请点击"/>
|
||||
<Hyperlink prefHeight="Infinity" text="此处"/>
|
||||
<Label prefHeight="Infinity" text="排查问题"/>
|
||||
@ -246,11 +246,12 @@
|
||||
<Label prefHeight="30" text="* 请勿将非法、暴力、色情等信息映射到外网上去,一经发现立即封号"/>
|
||||
</VBox>
|
||||
</Tab>
|
||||
<Tab text="使用场景">
|
||||
<VBox minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
|
||||
<!-- TODO 使用场景 -->
|
||||
<!-- <Tab text="使用场景">-->
|
||||
<!-- <VBox minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">-->
|
||||
|
||||
</VBox>
|
||||
</Tab>
|
||||
<!-- </VBox>-->
|
||||
<!-- </Tab>-->
|
||||
</tabs>
|
||||
</JFXTabPane>
|
||||
<JFXButton fx:id="clearLogBtn" layoutX="480.0" layoutY="-1.0" prefHeight="35.0" prefWidth="26.0"
|
||||
@ -263,13 +264,22 @@
|
||||
</cursor>
|
||||
</JFXButton>
|
||||
</AnchorPane>
|
||||
<VBox prefHeight="200.0" prefWidth="100.0" GridPane.columnIndex="1" GridPane.rowIndex="1">
|
||||
<VBox alignment="TOP_CENTER" prefHeight="200.0" prefWidth="100.0" GridPane.columnIndex="1"
|
||||
GridPane.rowIndex="1">
|
||||
<JFXButton fx:id="startProxyBtn" buttonType="RAISED" prefHeight="44.0" prefWidth="202.0"
|
||||
styleClass="startProxyBtn" text="启动">
|
||||
<cursor>
|
||||
<Cursor fx:constant="HAND"/>
|
||||
</cursor>
|
||||
</JFXButton>
|
||||
<JFXButton fx:id="logoutBtn" text="退出登录">
|
||||
<VBox.margin>
|
||||
<Insets top="20.0"/>
|
||||
</VBox.margin>
|
||||
<cursor>
|
||||
<Cursor fx:constant="HAND"/>
|
||||
</cursor>
|
||||
</JFXButton>
|
||||
</VBox>
|
||||
</children>
|
||||
</GridPane>
|
||||
|
Loading…
Reference in New Issue
Block a user