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