From 6f9df68e118d94ab0815c67abfd5bbe32e492ef0 Mon Sep 17 00:00:00 2001 From: "Leroy.H.Y" Date: Fri, 5 Jul 2019 23:47:31 +0800 Subject: [PATCH] [Remove] Removed Python depends. Added struct for vmess:// protocol. FYI: https://github.com/lhy0403/Qv2ray/issues/12#issuecomment-507897806 FYI: https://github.com/lhy0403/Qv2ray/issues/15 FYI: #15 Signed-off-by: Leroy.H.Y Former-commit-id: 361ff763e648448096106a8f6e06db14784cdda0 --- .appveyor.yml | 2 - .travis.yml | 2 +- CHANGELOG.md | 5 +- Qv2ray.pro | 59 +- README.md | 21 +- src/HUtils.cpp | 13 + src/HUtils.hpp | 11 +- src/V2ConfigObjects.hpp | 14 + src/main.cpp | 2 +- src/w_ConnectionEditWindow.cpp | 52 +- src/w_ConnectionEditWindow.h | 27 +- src/w_ConnectionEditWindow.ui | 8 +- src/w_ImportConfig.cpp | 215 +++-- src/w_ImportConfig.h | 38 +- src/w_ImportConfig.ui | 8 +- src/w_MainWindow.cpp | 469 +++++----- src/w_MainWindow.h | 86 +- src/w_MainWindow.ui | 4 +- src/w_PrefrencesWindow.cpp | 171 ++-- src/w_PrefrencesWindow.h | 46 +- src/w_PrefrencesWindow.ui | 8 +- tools/FixPythonWithMinGW.bat | 6 - tools/WindowsInstallDependencies.bat | 24 - tools/wget.exe.REMOVED.git-id | 1 - translations/en-US.ts | 1242 +++++++++++++------------- translations/zh-CN.ts | 1242 +++++++++++++------------- utils/vmess2json.py | 599 ------------- 27 files changed, 1837 insertions(+), 2538 deletions(-) delete mode 100644 tools/FixPythonWithMinGW.bat delete mode 100644 tools/WindowsInstallDependencies.bat delete mode 100644 tools/wget.exe.REMOVED.git-id delete mode 100755 utils/vmess2json.py diff --git a/.appveyor.yml b/.appveyor.yml index 5d1da84b..9c250429 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -5,8 +5,6 @@ install: - git submodule update --init build_script: - - mkdir python37 && xcopy C:\Python37 python37 /E /H /Q - - tools\FixPythonWithMinGW.bat - lrelease.exe Qv2ray.pro - mkdir build && cd build - qmake ..\Qv2ray.pro diff --git a/.travis.yml b/.travis.yml index 56f56d29..f6cc1634 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,7 +13,7 @@ before_install: - if [ "$BADGE" = "linux" ]; then sudo apt-get update; fi install: - - if [ "$BADGE" = "linux" ]; then sudo apt-get install qtchooser qt5-default qt5-qmake qtdeclarative5-dev python3-dev python-dev libpython3-dev qttools5-dev-tools; fi + - if [ "$BADGE" = "linux" ]; then sudo apt-get install qtchooser qt5-default qt5-qmake qtdeclarative5-dev qttools5-dev-tools; fi - if [ "$BADGE" = "osx" ]; then brew install cppcheck https://raw.githubusercontent.com/Homebrew/homebrew-core/master/Formula/qt.rb; fi - if [ "$BADGE" = "osx" ]; then brew link --force qt; fi diff --git a/CHANGELOG.md b/CHANGELOG.md index 7fb24328..2ad3a202 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,11 @@ # News ## 最新 -**2019-07-03**: 主配置文件序列化/反序列化工作完成,并添加更多协议配置 +**2019-07-04**: 我们终于摆脱了对于 Python 的依赖,现在 Qv2ray 可以自行解析 `vmess://` 协议 [WIP] ## 历史 + +**2019-07-03**: 主配置文件序列化/反序列化工作完成,并添加更多协议配置 + **2019-07-02**: 等待上游依赖完成更新 [JSON 序列化 std::list](https://github.com/xyz347/x2struct/issues/11#issuecomment-507671091) **2019-07-01**: 休息了几天,主要是去关注别的项目了。现在开始重构 v2ray 交互部分。 diff --git a/Qv2ray.pro b/Qv2ray.pro index f140b28c..bcf6d0ec 100644 --- a/Qv2ray.pro +++ b/Qv2ray.pro @@ -59,7 +59,8 @@ TRANSLATIONS += \ RC_ICONS += ./icons/Qv2ray.ico -INCLUDEPATH += 3rdparty/\ +INCLUDEPATH += \ + 3rdparty/\ 3rdparty/jsoncons/include @@ -67,59 +68,3 @@ INCLUDEPATH += 3rdparty/\ qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target - -WITH_PYTHON = no -PYTHONVER = null - -unix:!macx { - # Python Headers check. - exists( "/usr/include/python3.5m/Python.h" ) { - PYTHONVER = 3.5 - WITH_PYTHON = yes - } - exists( "/usr/include/python3.6m/Python.h" ) { - PYTHONVER = 3.6 - WITH_PYTHON = yes - } - exists( "/usr/include/python3.7m/Python.h" ) { - PYTHONVER = 3.7 - WITH_PYTHON = yes - } - - equals( WITH_PYTHON, "yes" ) { - INCLUDEPATH += /usr/include/python$${PYTHONVER}m/ - LIBS += -lpython$${PYTHONVER}m - message("Will build with python lib version $$PYTHONVER") - } -} - -macx { - PYTHON_ROOT=/usr/local/Cellar/python - exists( "$${PYTHON_ROOT}/3.6.5_1/" ) { - PYTHONVER = 3.6 - PYLDPATH=$${PYTHON_ROOT}/3.6.5_1/Frameworks/Python.framework/Versions/$${PYTHONVER} - WITH_PYTHON = yes - } - - exists( "$$PYTHON_ROOT/3.7.3/" ) { - PYTHONVER = 3.7 - PYLDPATH=$${PYTHON_ROOT}/3.7.3/Frameworks/Python.framework/Versions/$${PYTHONVER} - WITH_PYTHON = yes - } - - INCLUDEPATH += $${PYLDPATH}/include/python$${PYTHONVER}m/ - LIBS += -L$${PYLDPATH}/lib/python$${PYTHONVER}/config-$${PYTHONVER}m-darwin/ -lpython$${PYTHONVER}m - message("Will build with python lib version $$PYTHONVER") -} - -win32 { - exists( "$$PWD/python37/libs/libpython37_mingw.a" ) { - LIBS += -L$$PWD/python37/libs/ -lpython37_mingw - INCLUDEPATH += $$PWD/python37/include - WITH_PYTHON = yes - } -} - -equals(WITH_PYTHON, "no") { - error("No Python3 libs found, did you install dev packages such as python3-dev ?") -} diff --git a/README.md b/README.md index 51d6a5c9..fbe4a5b3 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,8 @@ -[![Codacy Badge](https://api.codacy.com/project/badge/Grade/a034dd186c36408c92ffb04449fb6996)](https://app.codacy.com/app/lhy0403/Qv2ray?utm_source=github.com&utm_medium=referral&utm_content=lhy0403/Qv2ray&utm_campaign=Badge_Grade_Dashboard) -# Qv2ray [![HitCount](http://hits.dwyl.io/lhy0403/Qv2ray.svg)](http://hits.dwyl.io/lhy0403/Qv2ray) +# Qv2ray TODO: 使用 Qt 的跨平台 v2ray 客户端,目前仍处于早期开发,多数功能尚未齐全。 -[![Language grade: C/C++](https://img.shields.io/lgtm/grade/cpp/g/lhy0403/Qv2ray.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/lhy0403/Qv2ray/context:cpp) [![Total alerts](https://img.shields.io/lgtm/alerts/g/lhy0403/Qv2ray.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/lhy0403/Qv2ray/alerts/) +[![Codacy Badge](https://api.codacy.com/project/badge/Grade/a034dd186c36408c92ffb04449fb6996)](https://app.codacy.com/app/lhy0403/Qv2ray?utm_source=github.com&utm_medium=referral&utm_content=lhy0403/Qv2ray&utm_campaign=Badge_Grade_Dashboard)[![HitCount](http://hits.dwyl.io/lhy0403/Qv2ray.svg)](http://hits.dwyl.io/lhy0403/Qv2ray)[![Language grade: C/C++](https://img.shields.io/lgtm/grade/cpp/g/lhy0403/Qv2ray.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/lhy0403/Qv2ray/context:cpp) [![Total alerts](https://img.shields.io/lgtm/alerts/g/lhy0403/Qv2ray.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/lhy0403/Qv2ray/alerts/) | OS | 主分支 [master](https://github.com/lhy0403/Qv2ray/tree/master) | 开发分支 [dev](https://github.com/lhy0403/Qv2ray/tree/dev) | | ------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | @@ -16,7 +15,7 @@ TODO: 使用 Qt 的跨平台 v2ray 客户端,目前仍处于早期开发,多 -# 鸣谢 +## 鸣谢 [@aliyuchang33](https://github.com/aliyuchang33) - 项目原作者/发起人,感谢他使用 Qt 作为基础框架。 @@ -24,18 +23,16 @@ TODO: 使用 Qt 的跨平台 v2ray 客户端,目前仍处于早期开发,多 -## 项目依赖包 +## 项目依赖 ### Linux -- Qt >= 5.12 -- Python (3.5 | 3.6 | 3.7) -### Windows -- Python 3.7 -- Qt Creator (MinGW & Qt5) +- `Qt >= 5.12` +- `gcc >=8` (需要 c++11 支持) +### Windows +Qt Creator (Qt5) -## MacOS +### MacOS - Qt >= 5.12 -- Python (3.6 | 3.7) 使用 [`brew install python3`] 解决依赖问题 ## 编译 - 如果想测试当前的开发分支,请使用 `git checkout dev` 切换到开发分支 diff --git a/src/HUtils.cpp b/src/HUtils.cpp index 14c88f71..faf4ecb5 100644 --- a/src/HUtils.cpp +++ b/src/HUtils.cpp @@ -26,6 +26,19 @@ namespace Qv2ray configFile->close(); } + QString base64_encode(QString string) + { + QByteArray ba; + ba.append(string); + return ba.toBase64(); + } + + QString base64_decode(QString string) + { + QByteArray ba; + ba.append(string); + return QString(QByteArray::fromBase64(ba)); + } void LoadConfig(QFile *configFile) { using namespace Qv2ray::QvConfigModels; diff --git a/src/HUtils.hpp b/src/HUtils.hpp index eb0a2617..8a311672 100644 --- a/src/HUtils.hpp +++ b/src/HUtils.hpp @@ -27,16 +27,13 @@ namespace Qv2ray /// Get file list in a Dir QStringList getAllFilesList(QDir *dir); bool hasFile(QDir *dir, QString fileName); - + QString base64_encode(QString string); + QString base64_decode(QString string); template QString StructToJSON(const TYPE &t) { string s; -#if USE_TODO_FEATURES - encode_json(t, s, indenting::indent); -#else s = X::tojson(t, "", 4, ' '); -#endif cout << s << endl; return QString::fromStdString(s); } @@ -45,11 +42,7 @@ namespace Qv2ray TYPE StructFromJSON(const string &str) { TYPE v; -#if USE_TODO_FEATURES - v = decode_json(str); -#else X::loadjson(str, v, false); -#endif return v; } } diff --git a/src/V2ConfigObjects.hpp b/src/V2ConfigObjects.hpp index c0d7ca11..97cad8f0 100644 --- a/src/V2ConfigObjects.hpp +++ b/src/V2ConfigObjects.hpp @@ -17,6 +17,20 @@ namespace Qv2ray { namespace V2ConfigModels { + struct VMessProtocolConfigObject { + string v; + string ps; + string add; + string port; + string id; + string aid; + string net; + string type; + string host; + string path; + string tls; + XTOSTRUCT(O(v, ps, add, port, id, aid, net, type, host, path, tls)) + }; // Two struct defining TYPE parameter to be passed into inbound configs and outbound configs. struct XOutBoundsType { }; diff --git a/src/main.cpp b/src/main.cpp index 8f8d8437..d9b35fe6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -92,7 +92,7 @@ int main(int argc, char *argv[]) } // Show MainWindow - Ui::MainWindow w; + MainWindow w; w.show(); return _qApp.exec(); } diff --git a/src/w_ConnectionEditWindow.cpp b/src/w_ConnectionEditWindow.cpp index 18c236f5..5a11370d 100644 --- a/src/w_ConnectionEditWindow.cpp +++ b/src/w_ConnectionEditWindow.cpp @@ -5,30 +5,32 @@ #include #include -namespace Ui + +ConnectionEditWindow::ConnectionEditWindow(QWidget *parent) + : QDialog(parent) + , ui(new Ui::ConnectionEditWindow) +{ + ui->setupUi(this); + ui->portLineEdit->setValidator(new QIntValidator()); + ui->alterLineEdit->setValidator(new QIntValidator()); +} + +ConnectionEditWindow::~ConnectionEditWindow() +{ + delete ui; +} + +//void ConnectionEditWindow::getConfigFromDialog(Ui::ConnectionEditWindow *ui) +//{ +//this->host = ui->ipLineEdit->text(); +//this->port = ui->portLineEdit->text(); +//this->alias = ui->aliasLineEdit->text(); +//this->uuid = ui->idLineEdit->text(); +//this->alterid = ui->alterLineEdit->text(); +//this->security = ui->securityCombo->currentText(); +//this->isCustom = 0; +//} + +void ConnectionEditWindow::on_buttonBox_accepted() { - ConnectionEditWindow::ConnectionEditWindow(QWidget *parent) - : QDialog(parent) - , ui(new Ui_WConnectionEdit) - { - ui->setupUi(this); - ui->portLineEdit->setValidator(new QIntValidator()); - ui->alterLineEdit->setValidator(new QIntValidator()); - } - - ConnectionEditWindow::~ConnectionEditWindow() - { - delete ui; - } - - //void ConnectionEditWindow::getConfigFromDialog(Ui::ConnectionEditWindow *ui) - //{ - //this->host = ui->ipLineEdit->text(); - //this->port = ui->portLineEdit->text(); - //this->alias = ui->aliasLineEdit->text(); - //this->uuid = ui->idLineEdit->text(); - //this->alterid = ui->alterLineEdit->text(); - //this->security = ui->securityCombo->currentText(); - //this->isCustom = 0; - //} } diff --git a/src/w_ConnectionEditWindow.h b/src/w_ConnectionEditWindow.h index 1c50565b..82a08b57 100644 --- a/src/w_ConnectionEditWindow.h +++ b/src/w_ConnectionEditWindow.h @@ -6,16 +6,21 @@ namespace Ui { - class ConnectionEditWindow : public QDialog - { - Q_OBJECT - - public: - explicit ConnectionEditWindow(QWidget *parent = nullptr); - ~ConnectionEditWindow(); - - private: - Ui_WConnectionEdit *ui; - }; + class ConnectionEditWindow; } + +class ConnectionEditWindow : public QDialog +{ + Q_OBJECT + + public: + explicit ConnectionEditWindow(QWidget *parent = nullptr); + ~ConnectionEditWindow(); + + private slots: + void on_buttonBox_accepted(); + + private: + Ui::ConnectionEditWindow *ui; +}; #endif // CONFEDIT_H diff --git a/src/w_ConnectionEditWindow.ui b/src/w_ConnectionEditWindow.ui index 3a988eee..0bbb1213 100644 --- a/src/w_ConnectionEditWindow.ui +++ b/src/w_ConnectionEditWindow.ui @@ -1,7 +1,7 @@ - WConnectionEdit - + ConnectionEditWindow + 0 @@ -864,7 +864,7 @@ buttonBox accepted() - WConnectionEdit + ConnectionEditWindow accept() @@ -880,7 +880,7 @@ buttonBox rejected() - WConnectionEdit + ConnectionEditWindow reject() diff --git a/src/w_ImportConfig.cpp b/src/w_ImportConfig.cpp index 0183da7b..79216ec2 100644 --- a/src/w_ImportConfig.cpp +++ b/src/w_ImportConfig.cpp @@ -5,131 +5,124 @@ #include #include -#pragma push_macro("slots") -#undef slots -#include "Python.h" -#pragma pop_macro("slots") - #include "HUtils.hpp" #include "vinteract.hpp" #include "w_ConnectionEditWindow.h" #include "w_ImportConfig.h" + using namespace Qv2ray; -namespace Ui +ImportConfig::ImportConfig(QWidget *parent) + : QDialog(parent) + , ui(new Ui::ImportConfigWindow) { - ImportConfig::ImportConfig(QWidget *parent) - : QDialog(parent) - , ui(new Ui_WImportConfig) - { - ui->setupUi(this); - connect(this, SIGNAL(updateConfTable()), parentWidget(), SLOT(updateConfTable())); - } + ui->setupUi(this); + connect(this, SIGNAL(updateConfTable()), parentWidget(), SLOT(updateConfTable())); +} - ImportConfig::~ImportConfig() - { - delete ui; - } +ImportConfig::~ImportConfig() +{ + delete ui; +} - void ImportConfig::on_pushButton_clicked() - { - QString dir = QFileDialog::getOpenFileName(this, tr("OpenConfigFile"), "~/"); - ui->fileLineTxt->setText(dir); - } +void ImportConfig::on_pushButton_clicked() +{ + QString dir = QFileDialog::getOpenFileName(this, tr("OpenConfigFile"), "~/"); + ui->fileLineTxt->setText(dir); +} - void ImportConfig::savefromFile(QString path, QString alias) - { - Q_UNUSED(path) - Q_UNUSED(alias) - //Hv2Config newConfig; - //newConfig.alias = alias; - //QFile configFile(path); - //if(!configFile.open(QIODevice::ReadOnly)) { - // showWarnMessageBox(this, tr("ImportConfig"), tr("CannotOpenFile")); - // qDebug() << "ImportConfig::CannotOpenFile"; - // return; - //} - //QByteArray allData = configFile.readAll(); - //configFile.close(); - //QJsonDocument v2conf(QJsonDocument::fromJson(allData)); - //QJsonObject rootobj = v2conf.object(); - //QJsonObject outbound; - //if(rootobj.contains("outbounds")) { - // outbound = rootobj.value("outbounds").toArray().first().toObject(); +void ImportConfig::savefromFile(QString path, QString alias) +{ + Q_UNUSED(path) + Q_UNUSED(alias) + //Hv2Config newConfig; + //newConfig.alias = alias; + //QFile configFile(path); + //if(!configFile.open(QIODevice::ReadOnly)) { + // showWarnMessageBox(this, tr("ImportConfig"), tr("CannotOpenFile")); + // qDebug() << "ImportConfig::CannotOpenFile"; + // return; + //} + //QByteArray allData = configFile.readAll(); + //configFile.close(); + //QJsonDocument v2conf(QJsonDocument::fromJson(allData)); + //QJsonObject rootobj = v2conf.object(); + //QJsonObject outbound; + //if(rootobj.contains("outbounds")) { + // outbound = rootobj.value("outbounds").toArray().first().toObject(); + //} else { + // outbound = rootobj.value("outbound").toObject(); + //} + //QJsonObject vnext = switchJsonArrayObject(outbound.value("settings").toObject(), "vnext"); + //QJsonObject user = switchJsonArrayObject(vnext, "users"); + //newConfig.host = vnext.value("address").toString(); + //newConfig.port = QString::number(vnext.value("port").toInt()); + //newConfig.alterid = QString::number(user.value("alterId").toInt()); + //newConfig.uuid = user.value("id").toString(); + //newConfig.security = user.value("security").toString(); + //if (newConfig.security.isNull()) { + // newConfig.security = "auto"; + //} + //newConfig.isCustom = 1; + //int id = newConfig.save(); + //if(id < 0) + //{ + // showWarnMessageBox(this, tr("ImportConfig"), tr("SaveFailed")); + // qDebug() << "ImportConfig::SaveFailed"; + // return; + //} + //emit updateConfTable(); + //QString newFile = "conf/" + QString::number(id) + ".conf"; + //if(!QFile::copy(path, newFile)) { + // showWarnMessageBox(this, tr("ImportConfig"), tr("CannotCopyCustomConfig")); + // qDebug() << "ImportConfig::CannotCopyCustomConfig"; + //} +} + +void ImportConfig::on_buttonBox_accepted() +{ + QString alias = ui->nameTxt->text(); + + if (ui->importSourceCombo->currentIndex() == 0) { // From File... + QString path = ui->fileLineTxt->text(); + bool isValid = v2Instance::checkConfigFile(path); + + if (!isValid) { + // Invalid file alert. + return; + } + + savefromFile(path, alias); + } else { + QString vmess = ui->vmessConnectionStringTxt->toPlainText(); + + if (!vmess.toLower().startsWith("vmess://")) { + Utils::showWarnMessageBox(this, tr("#VMessDecodeError"), tr("#NotValidVMessProtocolString")); + } + + QStringRef vmessJsonB64(&vmess, 8, vmess.length() - 8); + auto vmessString = Utils::base64_decode(vmessJsonB64.toString()); + auto vmessConf = Utils::StructFromJSON(vmessString.toStdString()); + // TODO: SAVE CONFIG!!!! + // + //if (QFile::exists(ConfigDir.path() + "/config.json.tmp")) { + // ImportConfig *im = new ImportConfig(this->parentWidget()); + // + // if (v2Instance::checkConfigFile(QCoreApplication::applicationDirPath() + "/config.json.tmp")) { + // im->savefromFile("config.json.tmp", alias); + // } + // + // QFile::remove("config.json.tmp"); //} else { - // outbound = rootobj.value("outbound").toObject(); - //} - //QJsonObject vnext = switchJsonArrayObject(outbound.value("settings").toObject(), "vnext"); - //QJsonObject user = switchJsonArrayObject(vnext, "users"); - //newConfig.host = vnext.value("address").toString(); - //newConfig.port = QString::number(vnext.value("port").toInt()); - //newConfig.alterid = QString::number(user.value("alterId").toInt()); - //newConfig.uuid = user.value("id").toString(); - //newConfig.security = user.value("security").toString(); - //if (newConfig.security.isNull()) { - // newConfig.security = "auto"; - //} - //newConfig.isCustom = 1; - //int id = newConfig.save(); - //if(id < 0) - //{ - // showWarnMessageBox(this, tr("ImportConfig"), tr("SaveFailed")); - // qDebug() << "ImportConfig::SaveFailed"; - // return; - //} - //emit updateConfTable(); - //QString newFile = "conf/" + QString::number(id) + ".conf"; - //if(!QFile::copy(path, newFile)) { - // showWarnMessageBox(this, tr("ImportConfig"), tr("CannotCopyCustomConfig")); - // qDebug() << "ImportConfig::CannotCopyCustomConfig"; + // Utils::showWarnMessageBox(this, tr("ImportConfig"), tr("CannotGenerateConfig")); + // qDebug() << "ImportConfig::CannotGenerateConfig"; //} } - void ImportConfig::on_buttonBox_accepted() - { - QString alias = ui->nameTxt->text(); - - if (ui->importSourceCombo->currentIndex() == 0) { // From File... - QString path = ui->fileLineTxt->text(); - bool isValid = v2Instance::checkConfigFile(path); - - if (isValid) { - savefromFile(path, alias); - } - } else { - QString vmess = ui->vmessConnectionStringTxt->toPlainText(); - Py_Initialize(); - assert(Py_IsInitialized()); - QString param = "--inbound socks:1080 " + vmess + " -o config.json.tmp"; - PyRun_SimpleString("import sys"); - PyRun_SimpleString("sys.path.append('./utils')"); - PyObject *pModule = PyImport_ImportModule("vmess2json"); - PyObject *pFunc = PyObject_GetAttrString(pModule, "main"); - PyObject *arg = PyTuple_New(1); - PyObject *arg1 = Py_BuildValue("s", param.toStdString().c_str()); - PyTuple_SetItem(arg, 0, arg1); - PyObject_CallObject(pFunc, arg); - Py_Finalize(); - - if (QFile::exists(QCoreApplication::applicationDirPath() + "/config.json.tmp")) { - ImportConfig *im = new ImportConfig(this->parentWidget()); - - if (v2Instance::checkConfigFile(QCoreApplication::applicationDirPath() + "/config.json.tmp")) { - im->savefromFile("config.json.tmp", alias); - } - - QFile::remove("config.json.tmp"); - } else { - Utils::showWarnMessageBox(this, tr("ImportConfig"), tr("CannotGenerateConfig")); - qDebug() << "ImportConfig::CannotGenerateConfig"; - } - } - - if (ui->useCurrentSettingRidBtn->isChecked()) { - // TODO: Use Current Settings... - } else { - // TODO: Override Inbound.... - } + if (ui->useCurrentSettingRidBtn->isChecked()) { + // TODO: Use Current Settings... + } else { + // TODO: Override Inbound.... } } diff --git a/src/w_ImportConfig.h b/src/w_ImportConfig.h index bf065104..ab7314e8 100644 --- a/src/w_ImportConfig.h +++ b/src/w_ImportConfig.h @@ -6,24 +6,26 @@ namespace Ui { - class ImportConfig : public QDialog - { - Q_OBJECT - - public: - explicit ImportConfig(QWidget *parent = nullptr); - void savefromFile(QString path, QString alias); - ~ImportConfig(); - - private slots: - void on_pushButton_clicked(); - void on_buttonBox_accepted(); - signals: - void updateConfTable(); - - private: - Ui_WImportConfig *ui; - }; + class ImportConfigWindow; } +class ImportConfig : public QDialog +{ + Q_OBJECT + + public: + explicit ImportConfig(QWidget *parent = nullptr); + void savefromFile(QString path, QString alias); + ~ImportConfig(); + + private slots: + void on_pushButton_clicked(); + void on_buttonBox_accepted(); + signals: + void updateConfTable(); + + private: + Ui::ImportConfigWindow *ui; +}; + #endif // IMPORTCONF_H diff --git a/src/w_ImportConfig.ui b/src/w_ImportConfig.ui index b25d14a7..85f31fbf 100644 --- a/src/w_ImportConfig.ui +++ b/src/w_ImportConfig.ui @@ -1,7 +1,7 @@ - WImportConfig - + ImportConfigWindow + 0 @@ -162,7 +162,7 @@ buttonBox accepted() - WImportConfig + ImportConfigWindow accept() @@ -178,7 +178,7 @@ buttonBox rejected() - WImportConfig + ImportConfigWindow reject() diff --git a/src/w_MainWindow.cpp b/src/w_MainWindow.cpp index b50ae500..3ebe2b1d 100644 --- a/src/w_MainWindow.cpp +++ b/src/w_MainWindow.cpp @@ -15,265 +15,262 @@ #include "w_MainWindow.h" #include "w_PrefrencesWindow.h" -namespace Ui +void MainWindow::CreateTrayIcon() { - void MainWindow::CreateTrayIcon() - { - hTray = new QSystemTrayIcon(); - hTray->setToolTip(tr("Qv2ray")); - hTray->setIcon(this->windowIcon()); - connect(hTray, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(on_activatedTray(QSystemTrayIcon::ActivationReason))); - QAction *actionShow = new QAction(this); - QAction *actionQuit = new QAction(this); - QAction *actionStart = new QAction(this); - QAction *actionRestart = new QAction(this); - QAction *actionStop = new QAction(this); - actionShow->setText(tr("#Hide")); - actionQuit->setText(tr("#Quit")); - actionStart->setText(tr("#Start")); - actionStop->setText(tr("#Stop")); - actionRestart->setText(tr("#Restart")); - actionStart->setEnabled(true); - actionStop->setEnabled(false); - actionRestart->setEnabled(false); - trayMenu->addAction(actionShow); - trayMenu->addSeparator(); - trayMenu->addAction(actionStart); - trayMenu->addAction(actionStop); - trayMenu->addAction(actionRestart); - trayMenu->addSeparator(); - trayMenu->addAction(actionQuit); - connect(actionShow, SIGNAL(triggered()), this, SLOT(toggleMainWindowVisibility())); - connect(actionStart, SIGNAL(triggered()), this, SLOT(on_startButton_clicked())); - connect(actionStop, SIGNAL(triggered()), this, SLOT(on_stopButton_clicked())); - connect(actionRestart, SIGNAL(triggered()), this, SLOT(on_restartButton_clicked())); - connect(actionQuit, SIGNAL(triggered()), this, SLOT(quit())); - hTray->setContextMenu(trayMenu); - hTray->show(); + hTray = new QSystemTrayIcon(); + hTray->setToolTip(tr("Qv2ray")); + hTray->setIcon(this->windowIcon()); + connect(hTray, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(on_activatedTray(QSystemTrayIcon::ActivationReason))); + QAction *actionShow = new QAction(this); + QAction *actionQuit = new QAction(this); + QAction *actionStart = new QAction(this); + QAction *actionRestart = new QAction(this); + QAction *actionStop = new QAction(this); + actionShow->setText(tr("#Hide")); + actionQuit->setText(tr("#Quit")); + actionStart->setText(tr("#Start")); + actionStop->setText(tr("#Stop")); + actionRestart->setText(tr("#Restart")); + actionStart->setEnabled(true); + actionStop->setEnabled(false); + actionRestart->setEnabled(false); + trayMenu->addAction(actionShow); + trayMenu->addSeparator(); + trayMenu->addAction(actionStart); + trayMenu->addAction(actionStop); + trayMenu->addAction(actionRestart); + trayMenu->addSeparator(); + trayMenu->addAction(actionQuit); + connect(actionShow, SIGNAL(triggered()), this, SLOT(toggleMainWindowVisibility())); + connect(actionStart, SIGNAL(triggered()), this, SLOT(on_startButton_clicked())); + connect(actionStop, SIGNAL(triggered()), this, SLOT(on_stopButton_clicked())); + connect(actionRestart, SIGNAL(triggered()), this, SLOT(on_restartButton_clicked())); + connect(actionQuit, SIGNAL(triggered()), this, SLOT(quit())); + hTray->setContextMenu(trayMenu); + hTray->show(); +} + +MainWindow::MainWindow(QWidget *parent) + : QMainWindow(parent) + , ui(new Ui::MainWindow) +{ + this->setWindowIcon(QIcon(":/icons/Qv2ray.ico")); + ui->setupUi(this); + UpdateConfigTable(); + // ui->configTable->setContextMenuPolicy(Qt::CustomContextMenu); + // connect(ui->configTable, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showMenu(QPoint))); + this->vinstance = new Qv2ray::v2Instance(this); + CreateTrayIcon(); + + if (QFileInfo("config.json").exists()) { + vinstance->start(); } - MainWindow::MainWindow(QWidget *parent) - : QMainWindow(parent) - , ui(new Ui_WMain) - { - this->setWindowIcon(QIcon(":/icons/Qv2ray.ico")); - ui->setupUi(this); - UpdateConfigTable(); - // ui->configTable->setContextMenuPolicy(Qt::CustomContextMenu); - // connect(ui->configTable, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showMenu(QPoint))); - this->vinstance = new Qv2ray::v2Instance(this); - CreateTrayIcon(); + // QAction *select = new QAction("Select", ui->configTable); + // QAction *del = new QAction("Delete", ui->configTable); + // QAction *rename = new QAction("Rename", ui->configTable); + // popMenu->addAction(select); + // popMenu->addAction(del); + // popMenu->addAction(rename); + // connect(select, SIGNAL(triggered()), this, SLOT(select_triggered())); + // connect(del, SIGNAL(triggered()), this, SLOT(delConf())); + // connect(rename, SIGNAL(triggered()), this, SLOT(renameRow())); + // connect(ui->logText, SIGNAL(textChanged()), this, SLOT(scrollToBottom())); + // bar = ui->logText->verticalScrollBar(); +} - if (QFileInfo("config.json").exists()) { - vinstance->start(); - } +MainWindow::~MainWindow() +{ + hTray->hide(); + delete this->hTray; + delete this->vinstance; + delete ui; +} - // QAction *select = new QAction("Select", ui->configTable); - // QAction *del = new QAction("Delete", ui->configTable); - // QAction *rename = new QAction("Rename", ui->configTable); - // popMenu->addAction(select); - // popMenu->addAction(del); - // popMenu->addAction(rename); - // connect(select, SIGNAL(triggered()), this, SLOT(select_triggered())); - // connect(del, SIGNAL(triggered()), this, SLOT(delConf())); - // connect(rename, SIGNAL(triggered()), this, SLOT(renameRow())); - // connect(ui->logText, SIGNAL(textChanged()), this, SLOT(scrollToBottom())); - // bar = ui->logText->verticalScrollBar(); - } +void MainWindow::on_actionEdit_triggered() +{ + ConnectionEditWindow *e = new ConnectionEditWindow(this); + e->setAttribute(Qt::WA_DeleteOnClose); + e->show(); +} - MainWindow::~MainWindow() - { - hTray->hide(); - delete this->hTray; - delete this->vinstance; - delete ui; - } +void MainWindow::on_actionExisting_config_triggered() +{ + ImportConfig *f = new ImportConfig(this); + f->setAttribute(Qt::WA_DeleteOnClose); + f->show(); +} - void MainWindow::on_actionEdit_triggered() - { - ConnectionEditWindow *e = new ConnectionEditWindow(this); - e->setAttribute(Qt::WA_DeleteOnClose); - e->show(); - } +void MainWindow::showMenu(QPoint pos) +{ + Q_UNUSED(pos) + // if(ui->configTable->indexAt(pos).column() != -1) { + // popMenu->move(cursor().pos()); + // popMenu->show(); + // } +} +void MainWindow::select_triggered() +{ + // int row = ui->configTable->selectionModel()->currentIndex().row(); + // int idIntable = ui->configTable->model()->data(ui->configTable->model()->index(row, 4)).toInt(); + // this->geneConf(idIntable); + // if(this->v2Inst->v2Process->state() == QProcess::Running) { + // this->on_restartButton_clicked(); + // } +} - void MainWindow::on_actionExisting_config_triggered() - { - ImportConfig *f = new ImportConfig(this); - f->setAttribute(Qt::WA_DeleteOnClose); - f->show(); - } +void MainWindow::DeleteConfig() +{ +} +void MainWindow::UpdateConfigTable() +{ +} +void MainWindow::GenerateConfig(int idIntable) +{ + Q_UNUSED(idIntable) + //Hv2Config tmpConf; + //emit UpdateConfigTable(); + //if (tmpConf.isCustom == 1) { + // QString src = "conf/" + QString::number(idIntable) + ".conf"; + // overrideInbounds(src); + // if (QFile::exists("config.json")) { + // QFile::remove("config.json"); + // } + // QFile::copy(src, "config.json"); + //} else { + // // TODO: Config generator + //} +} +void MainWindow::UpdateLog() +{ + ui->logText->insertPlainText(this->vinstance->vProcess->readAllStandardOutput()); +} - void MainWindow::showMenu(QPoint pos) - { - Q_UNUSED(pos) - // if(ui->configTable->indexAt(pos).column() != -1) { - // popMenu->move(cursor().pos()); - // popMenu->show(); - // } - } - void MainWindow::select_triggered() - { - // int row = ui->configTable->selectionModel()->currentIndex().row(); - // int idIntable = ui->configTable->model()->data(ui->configTable->model()->index(row, 4)).toInt(); - // this->geneConf(idIntable); - // if(this->v2Inst->v2Process->state() == QProcess::Running) { - // this->on_restartButton_clicked(); - // } - } +void MainWindow::on_startButton_clicked() +{ + ui->logText->clear(); + bool startFlag = this->vinstance->start(); + trayMenu->actions()[2]->setEnabled(!startFlag); + trayMenu->actions()[3]->setEnabled(startFlag); + trayMenu->actions()[4]->setEnabled(startFlag); +} - void MainWindow::DeleteConfig() - { - } - void MainWindow::UpdateConfigTable() - { - } - void MainWindow::GenerateConfig(int idIntable) - { - Q_UNUSED(idIntable) - //Hv2Config tmpConf; - //emit UpdateConfigTable(); - //if (tmpConf.isCustom == 1) { - // QString src = "conf/" + QString::number(idIntable) + ".conf"; - // overrideInbounds(src); - // if (QFile::exists("config.json")) { - // QFile::remove("config.json"); - // } - // QFile::copy(src, "config.json"); - //} else { - // // TODO: Config generator - //} - } - void MainWindow::UpdateLog() - { - ui->logText->insertPlainText(this->vinstance->vProcess->readAllStandardOutput()); - } +void MainWindow::on_stopButton_clicked() +{ + this->vinstance->stop(); + ui->logText->clear(); + trayMenu->actions()[2]->setEnabled(true); + trayMenu->actions()[3]->setEnabled(false); + trayMenu->actions()[4]->setEnabled(false); +} - void MainWindow::on_startButton_clicked() - { - ui->logText->clear(); - bool startFlag = this->vinstance->start(); - trayMenu->actions()[2]->setEnabled(!startFlag); - trayMenu->actions()[3]->setEnabled(startFlag); - trayMenu->actions()[4]->setEnabled(startFlag); - } +void MainWindow::on_restartButton_clicked() +{ + on_stopButton_clicked(); + on_startButton_clicked(); +} - void MainWindow::on_stopButton_clicked() - { - this->vinstance->stop(); - ui->logText->clear(); - trayMenu->actions()[2]->setEnabled(true); - trayMenu->actions()[3]->setEnabled(false); - trayMenu->actions()[4]->setEnabled(false); - } +void MainWindow::on_clbutton_clicked() +{ + ui->logText->clear(); +} - void MainWindow::on_restartButton_clicked() - { - on_stopButton_clicked(); - on_startButton_clicked(); - } +void MainWindow::on_rtButton_clicked() +{ + emit UpdateConfigTable(); +} - void MainWindow::on_clbutton_clicked() - { - ui->logText->clear(); - } +void MainWindow::closeEvent(QCloseEvent *event) +{ + this->hide(); + event->ignore(); +} - void MainWindow::on_rtButton_clicked() - { - emit UpdateConfigTable(); - } - - void MainWindow::closeEvent(QCloseEvent *event) - { - this->hide(); - event->ignore(); - } - - void MainWindow::on_activatedTray(QSystemTrayIcon::ActivationReason reason) - { - switch (reason) { - case QSystemTrayIcon::Trigger: - // Toggle Show/Hide +void MainWindow::on_activatedTray(QSystemTrayIcon::ActivationReason reason) +{ + switch (reason) { + case QSystemTrayIcon::Trigger: + // Toggle Show/Hide #ifndef __APPLE__ - // Every single click will trigger the Show/Hide toggling. - // So, as a hobby on common MacOS Apps, we 'don't toggle visibility on click'. - toggleMainWindowVisibility(); + // Every single click will trigger the Show/Hide toggling. + // So, as a hobby on common MacOS Apps, we 'don't toggle visibility on click'. + toggleMainWindowVisibility(); #endif - break; + break; - case QSystemTrayIcon::DoubleClick: - if (this->isHidden()) { - this->show(); - } + case QSystemTrayIcon::DoubleClick: + if (this->isHidden()) { + this->show(); + } - break; + break; - case QSystemTrayIcon::MiddleClick: + case QSystemTrayIcon::MiddleClick: - // TODO: Check if an alert message box is present. - // If so, do nothing but please wait for the message box to be closed. - if (this->vinstance->vProcess->state() == QProcess::ProcessState::Running) { - on_stopButton_clicked(); - } else { - on_startButton_clicked(); - } + // TODO: Check if an alert message box is present. + // If so, do nothing but please wait for the message box to be closed. + if (this->vinstance->vProcess->state() == QProcess::ProcessState::Running) { + on_stopButton_clicked(); + } else { + on_startButton_clicked(); + } - break; + break; - case QSystemTrayIcon::Unknown: - break; + case QSystemTrayIcon::Unknown: + break; - case QSystemTrayIcon::Context: - break; - } - } - - void MainWindow::toggleMainWindowVisibility() - { - if (this->isHidden()) { - this->show(); - trayMenu->actions()[0]->setText(tr("#Hide")); - } else { - this->hide(); - trayMenu->actions()[0]->setText(tr("#Show")); - } - } - - void MainWindow::quit() - { - QCoreApplication::quit(); - } - - void MainWindow::on_actionExit_triggered() - { - quit(); - } - - void MainWindow::renameRow() - { - // QString text = QInputDialog::getText(this, "Rename config", "New name:", QLineEdit::Normal); - // int row = ui->configTable->currentIndex().row(); - // int idIntable = ui->configTable->model()->data(ui->configTable->model()->index(row, 4)).toInt(); - // SQLiteDB mydb; - // QString updateString = "update confs set alias = '" + text + "' where id = " + QString::number(idIntable); - // mydb.DoQuery(updateString); - // emit updateConfTable(); - } - - void MainWindow::scrollToBottom() - { - bar->setValue(bar->maximum()); - } - - void MainWindow::on_actionPreferences_triggered() - { - PrefrencesWindow *v = new PrefrencesWindow(this); - v->setAttribute(Qt::WA_DeleteOnClose); - v->show(); - } - - void MainWindow::on_pushButton_clicked() - { - auto confedit = new ConnectionEditWindow(); - confedit->show(); + case QSystemTrayIcon::Context: + break; } } + +void MainWindow::toggleMainWindowVisibility() +{ + if (this->isHidden()) { + this->show(); + trayMenu->actions()[0]->setText(tr("#Hide")); + } else { + this->hide(); + trayMenu->actions()[0]->setText(tr("#Show")); + } +} + +void MainWindow::quit() +{ + QCoreApplication::quit(); +} + +void MainWindow::on_actionExit_triggered() +{ + quit(); +} + +void MainWindow::renameRow() +{ + // QString text = QInputDialog::getText(this, "Rename config", "New name:", QLineEdit::Normal); + // int row = ui->configTable->currentIndex().row(); + // int idIntable = ui->configTable->model()->data(ui->configTable->model()->index(row, 4)).toInt(); + // SQLiteDB mydb; + // QString updateString = "update confs set alias = '" + text + "' where id = " + QString::number(idIntable); + // mydb.DoQuery(updateString); + // emit updateConfTable(); +} + +void MainWindow::scrollToBottom() +{ + bar->setValue(bar->maximum()); +} + +void MainWindow::on_actionPreferences_triggered() +{ + PrefrencesWindow *v = new PrefrencesWindow(this); + v->setAttribute(Qt::WA_DeleteOnClose); + v->show(); +} + +void MainWindow::on_pushButton_clicked() +{ + auto confedit = new ConnectionEditWindow(); + confedit->show(); +} diff --git a/src/w_MainWindow.h b/src/w_MainWindow.h index e97e0c76..72c58578 100644 --- a/src/w_MainWindow.h +++ b/src/w_MainWindow.h @@ -10,52 +10,52 @@ #include "vinteract.hpp" #include "V2ConfigObjects.hpp" - namespace Ui { - class MainWindow : public QMainWindow - { - Q_OBJECT - public: - explicit MainWindow(QWidget *parent = nullptr); - Qv2ray::v2Instance *vinstance; - QSystemTrayIcon *hTray; - QMenu *trayMenu = new QMenu(this); - QMenu *popMenu = new QMenu(this); - QScrollBar *bar; - ~MainWindow(); - - private slots: - void on_restartButton_clicked(); - void on_actionEdit_triggered(); - void on_actionExisting_config_triggered(); - void UpdateConfigTable(); - void DeleteConfig(); - void showMenu(QPoint pos); - void UpdateLog(); - void on_startButton_clicked(); - void on_stopButton_clicked(); - void select_triggered(); - void on_clbutton_clicked(); - void on_rtButton_clicked(); - void GenerateConfig(int idIntable); - void on_activatedTray(QSystemTrayIcon::ActivationReason reason); - void toggleMainWindowVisibility(); - void quit(); - void on_actionExit_triggered(); - void renameRow(); - void scrollToBottom(); - void on_actionPreferences_triggered(); - - void on_pushButton_clicked(); - - private: - Ui_WMain *ui; - void closeEvent(QCloseEvent *); - void createTrayAction(); - void CreateTrayIcon(); - }; + class MainWindow; } +class MainWindow : public QMainWindow +{ + Q_OBJECT + public: + explicit MainWindow(QWidget *parent = nullptr); + Qv2ray::v2Instance *vinstance; + QSystemTrayIcon *hTray; + QMenu *trayMenu = new QMenu(this); + QMenu *popMenu = new QMenu(this); + QScrollBar *bar; + ~MainWindow(); + + private slots: + void on_restartButton_clicked(); + void on_actionEdit_triggered(); + void on_actionExisting_config_triggered(); + void UpdateConfigTable(); + void DeleteConfig(); + void showMenu(QPoint pos); + void UpdateLog(); + void on_startButton_clicked(); + void on_stopButton_clicked(); + void select_triggered(); + void on_clbutton_clicked(); + void on_rtButton_clicked(); + void GenerateConfig(int idIntable); + void on_activatedTray(QSystemTrayIcon::ActivationReason reason); + void toggleMainWindowVisibility(); + void quit(); + void on_actionExit_triggered(); + void renameRow(); + void scrollToBottom(); + void on_actionPreferences_triggered(); + + void on_pushButton_clicked(); + + private: + Ui::MainWindow *ui; + void closeEvent(QCloseEvent *); + void createTrayAction(); + void CreateTrayIcon(); +}; #endif // MAINWINDOW_H diff --git a/src/w_MainWindow.ui b/src/w_MainWindow.ui index 7654679a..15f196f3 100644 --- a/src/w_MainWindow.ui +++ b/src/w_MainWindow.ui @@ -1,7 +1,7 @@ - WMain - + MainWindow + 0 diff --git a/src/w_PrefrencesWindow.cpp b/src/w_PrefrencesWindow.cpp index eb95a3a9..d4bd4224 100644 --- a/src/w_PrefrencesWindow.cpp +++ b/src/w_PrefrencesWindow.cpp @@ -18,100 +18,97 @@ using namespace Qv2ray::Utils; -namespace Ui +PrefrencesWindow::PrefrencesWindow(QWidget *parent) : QDialog(parent), + CurrentConfig(), + ui(new Ui::PrefrencesWindow) { - PrefrencesWindow::PrefrencesWindow(QWidget *parent) : QDialog(parent), - CurrentConfig(), - ui(new Ui_WPrefrences) - { - ui->setupUi(this); - CurrentConfig = GetGlobalConfig(); - ui->languageComboBox->setCurrentText(QString::fromStdString(CurrentConfig.language)); - ui->runAsRootCheckBox->setChecked(CurrentConfig.runAsRoot); - ui->logLevelCheckBox->setCurrentText(QString::fromStdString(CurrentConfig.logLevel)); - // - ui->httpCB->setChecked(CurrentConfig.httpSetting.enabled); - ui->httpPortLE->setText(QString::fromStdString(to_string(CurrentConfig.httpSetting.port))); - ui->httpAuthCB->setChecked(CurrentConfig.httpSetting.useAuthentication); - ui->httpAuthUsernameTxt->setText(QString::fromStdString(CurrentConfig.httpSetting.authUsername)); - ui->httpAuthPasswordTxt->setText(QString::fromStdString(CurrentConfig.httpSetting.authPassword)); - ui->httpPortLE->setValidator(new QIntValidator()); - // - ui->socksCB->setChecked(CurrentConfig.socksSetting.enabled); - ui->socksPortLE->setText(QString::fromStdString(to_string(CurrentConfig.socksSetting.port))); - ui->socksAuthCB->setChecked(CurrentConfig.socksSetting.useAuthentication); - ui->socksAuthUsernameTxt->setText(QString::fromStdString(CurrentConfig.socksSetting.authUsername)); - ui->socksAuthPasswordTxt->setText(QString::fromStdString(CurrentConfig.socksSetting.authPassword)); - // - ui->httpPortLE->setValidator(new QIntValidator()); - ui->socksPortLE->setValidator(new QIntValidator()); - parentMW = parent; - } + ui->setupUi(this); + CurrentConfig = GetGlobalConfig(); + ui->languageComboBox->setCurrentText(QString::fromStdString(CurrentConfig.language)); + ui->runAsRootCheckBox->setChecked(CurrentConfig.runAsRoot); + ui->logLevelCheckBox->setCurrentText(QString::fromStdString(CurrentConfig.logLevel)); + // + ui->httpCB->setChecked(CurrentConfig.httpSetting.enabled); + ui->httpPortLE->setText(QString::fromStdString(to_string(CurrentConfig.httpSetting.port))); + ui->httpAuthCB->setChecked(CurrentConfig.httpSetting.useAuthentication); + ui->httpAuthUsernameTxt->setText(QString::fromStdString(CurrentConfig.httpSetting.authUsername)); + ui->httpAuthPasswordTxt->setText(QString::fromStdString(CurrentConfig.httpSetting.authPassword)); + ui->httpPortLE->setValidator(new QIntValidator()); + // + ui->socksCB->setChecked(CurrentConfig.socksSetting.enabled); + ui->socksPortLE->setText(QString::fromStdString(to_string(CurrentConfig.socksSetting.port))); + ui->socksAuthCB->setChecked(CurrentConfig.socksSetting.useAuthentication); + ui->socksAuthUsernameTxt->setText(QString::fromStdString(CurrentConfig.socksSetting.authUsername)); + ui->socksAuthPasswordTxt->setText(QString::fromStdString(CurrentConfig.socksSetting.authPassword)); + // + ui->httpPortLE->setValidator(new QIntValidator()); + ui->socksPortLE->setValidator(new QIntValidator()); + parentMW = parent; +} - PrefrencesWindow::~PrefrencesWindow() - { - delete ui; - } +PrefrencesWindow::~PrefrencesWindow() +{ + delete ui; +} - void PrefrencesWindow::on_buttonBox_accepted() - { - if (Qv2ray::v2Instance::checkVCoreExes()) { - if (ui->httpPortLE->text().toInt() != ui->socksPortLE->text().toInt()) { +void PrefrencesWindow::on_buttonBox_accepted() +{ + if (Qv2ray::v2Instance::checkVCoreExes()) { + if (ui->httpPortLE->text().toInt() != ui->socksPortLE->text().toInt()) { #ifndef _WIN32 - // Set UID and GID in *nix - // The file is actually not here - QFileInfo v2rayCoreExeFile("v2ray"); + // Set UID and GID in *nix + // The file is actually not here + QFileInfo v2rayCoreExeFile("v2ray"); - if (ui->runAsRootCheckBox->isChecked() && v2rayCoreExeFile.ownerId() != 0) { - QProcess::execute("pkexec", QStringList() << "bash" - << "-c" - << "chown root:root " + QCoreApplication::applicationDirPath() + "/v2ray" + ";chmod +s " + QCoreApplication::applicationDirPath() + "/v2ray"); - } else if (!ui->runAsRootCheckBox->isChecked() && v2rayCoreExeFile.ownerId() == 0) { - uid_t uid = getuid(); - gid_t gid = getgid(); - QProcess::execute("pkexec", QStringList() << "chown" << QString::number(uid) + ":" + QString::number(gid) << QCoreApplication::applicationDirPath() + "/v2ray"); - } - - v2rayCoreExeFile.refresh(); - //rootObj.insert("v2suidEnabled", v2rayCoreExeFile.ownerId() == 0); -#else - // No such uid gid thing on windows.... -#endif - } else { - showWarnMessageBox(this, tr("Prefrences"), tr("PortNumbersCannotBeSame")); + if (ui->runAsRootCheckBox->isChecked() && v2rayCoreExeFile.ownerId() != 0) { + QProcess::execute("pkexec", QStringList() << "bash" + << "-c" + << "chown root:root " + QCoreApplication::applicationDirPath() + "/v2ray" + ";chmod +s " + QCoreApplication::applicationDirPath() + "/v2ray"); + } else if (!ui->runAsRootCheckBox->isChecked() && v2rayCoreExeFile.ownerId() == 0) { + uid_t uid = getuid(); + gid_t gid = getgid(); + QProcess::execute("pkexec", QStringList() << "chown" << QString::number(uid) + ":" + QString::number(gid) << QCoreApplication::applicationDirPath() + "/v2ray"); } - } - } - void PrefrencesWindow::on_httpCB_stateChanged(int checked) - { - if (checked != Qt::Checked) { - ui->httpPortLE->setDisabled(true); - } else { - ui->httpPortLE->setEnabled(true); - } - } - - void PrefrencesWindow::on_socksCB_stateChanged(int checked) - { - if (checked != Qt::Checked) { - ui->socksPortLE->setEnabled(false); - } else { - ui->socksPortLE->setEnabled(true); - } - } - - void PrefrencesWindow::on_httpAuthCB_stateChanged(int checked) - { - if (checked) { - } - } - - void PrefrencesWindow::on_runAsRootCheckBox_stateChanged(int arg1) - { - Q_UNUSED(arg1) -#ifdef _WIN32 - showWarnMessageBox(this, tr("Prefrences"), tr("RunAsRootNotOnWindows")); + v2rayCoreExeFile.refresh(); + //rootObj.insert("v2suidEnabled", v2rayCoreExeFile.ownerId() == 0); +#else + // No such uid gid thing on windows.... #endif + } else { + showWarnMessageBox(this, tr("Prefrences"), tr("PortNumbersCannotBeSame")); + } } } + +void PrefrencesWindow::on_httpCB_stateChanged(int checked) +{ + if (checked != Qt::Checked) { + ui->httpPortLE->setDisabled(true); + } else { + ui->httpPortLE->setEnabled(true); + } +} + +void PrefrencesWindow::on_socksCB_stateChanged(int checked) +{ + if (checked != Qt::Checked) { + ui->socksPortLE->setEnabled(false); + } else { + ui->socksPortLE->setEnabled(true); + } +} + +void PrefrencesWindow::on_httpAuthCB_stateChanged(int checked) +{ + if (checked) { + } +} + +void PrefrencesWindow::on_runAsRootCheckBox_stateChanged(int arg1) +{ + Q_UNUSED(arg1) +#ifdef _WIN32 + showWarnMessageBox(this, tr("Prefrences"), tr("RunAsRootNotOnWindows")); +#endif +} diff --git a/src/w_PrefrencesWindow.h b/src/w_PrefrencesWindow.h index 41b89e73..ae3b803e 100644 --- a/src/w_PrefrencesWindow.h +++ b/src/w_PrefrencesWindow.h @@ -7,27 +7,29 @@ namespace Ui { - class PrefrencesWindow : public QDialog - { - Q_OBJECT - - public: - explicit PrefrencesWindow(QWidget *parent = nullptr); - ~PrefrencesWindow(); - QWidget *parentMW; - - private slots: - void on_buttonBox_accepted(); - void on_httpCB_stateChanged(int arg1); - void on_socksCB_stateChanged(int arg1); - - void on_httpAuthCB_stateChanged(int arg1); - - void on_runAsRootCheckBox_stateChanged(int arg1); - - private: - Qv2ray::QvConfigModels::Qv2Config CurrentConfig; - Ui_WPrefrences *ui; - }; + class PrefrencesWindow; } + +class PrefrencesWindow : public QDialog +{ + Q_OBJECT + + public: + explicit PrefrencesWindow(QWidget *parent = nullptr); + ~PrefrencesWindow(); + QWidget *parentMW; + + private slots: + void on_buttonBox_accepted(); + void on_httpCB_stateChanged(int arg1); + void on_socksCB_stateChanged(int arg1); + + void on_httpAuthCB_stateChanged(int arg1); + + void on_runAsRootCheckBox_stateChanged(int arg1); + + private: + Qv2ray::QvConfigModels::Qv2Config CurrentConfig; + Ui::PrefrencesWindow *ui; +}; #endif // HVCONF_H diff --git a/src/w_PrefrencesWindow.ui b/src/w_PrefrencesWindow.ui index 30869764..12586791 100644 --- a/src/w_PrefrencesWindow.ui +++ b/src/w_PrefrencesWindow.ui @@ -1,7 +1,7 @@ - WPrefrences - + PrefrencesWindow + 0 @@ -345,7 +345,7 @@ buttonBox accepted() - WPrefrences + PrefrencesWindow accept() @@ -361,7 +361,7 @@ buttonBox rejected() - WPrefrences + PrefrencesWindow reject() diff --git a/tools/FixPythonWithMinGW.bat b/tools/FixPythonWithMinGW.bat deleted file mode 100644 index 3ab8766a..00000000 --- a/tools/FixPythonWithMinGW.bat +++ /dev/null @@ -1,6 +0,0 @@ -set CURRENT_PATH=%~dp0% -cd %~dp0\..\python37\libs\ -echo EXPORTS > python37.def -nm python37.lib | grep " T _" | sed "s/.* T _//" >> python37.def -dlltool --input-def python37.def --dllname python37 --output-lib libpython37_mingw.a -cd %CURRENT_PATH%\..\ diff --git a/tools/WindowsInstallDependencies.bat b/tools/WindowsInstallDependencies.bat deleted file mode 100644 index 75e1df43..00000000 --- a/tools/WindowsInstallDependencies.bat +++ /dev/null @@ -1,24 +0,0 @@ -@echo off -REM Install Python - -ECHO Downloading Python using wget... -%~dp0\wget.exe https://www.python.org/ftp/python/3.7.3/python-3.7.3.exe -O %~dp0\python-3.7.3.exe - -REM Get install path -CALL :NORMALIZEPATH "\python37\" -ECHO INSTALL_PATH=%RETVAL% - -REM Installing Python... -start /w "" "%~dp0\python-3.7.3.exe" /quiet TargetDir=%RETVAL% - -:CONTINUE -ECHO Python headers and libs are installed! -exit 0 - -REM ======================================================================================== - -REM Path resolving using: https://stackoverflow.com/a/33404867/8364323 -:: ========== FUNCTIONS ========== -:NORMALIZEPATH - SET RETVAL=%~dpfn1 - EXIT /B \ No newline at end of file diff --git a/tools/wget.exe.REMOVED.git-id b/tools/wget.exe.REMOVED.git-id deleted file mode 100644 index df6f2392..00000000 --- a/tools/wget.exe.REMOVED.git-id +++ /dev/null @@ -1 +0,0 @@ -e21dde78d551a377ba813f6079ed610deaafadd8 \ No newline at end of file diff --git a/translations/en-US.ts b/translations/en-US.ts index 7244b12e..41afa686 100644 --- a/translations/en-US.ts +++ b/translations/en-US.ts @@ -1,6 +1,619 @@ + + ConnectionEditWindow + + + #ConnectionSettings + Connection Settings + + + + + #Host + Host + + + + #Port + Port + + + + #Name + Name + + + + #UUID + UUID + + + + #AlterID + Alter ID + + + + + #Security + Security Settings + + + + auto + Auto + + + + + aes-128-gcm + aes-128-gcm + + + + + chacha20-poly1305 + chacha20-poly1305 + + + + + + + + none + Do not use + + + + #Transport + Transport Settings + + + + tcp (TCP) + tcp (TCP) + + + + http (HTTP) + http (HTTP) + + + + ws (WebSocket) + ws (WebSocket) + + + + kcp (mKCP) + kcp (mKCP) + + + + domainsocket (Domain Socket) + domainsocket (Domain Socket) + + + + quic (Quick UDP Internet Connection) + quic (Quick UDP Internet Connection) + + + + #TransportSettings + Transport Settings + + + + TCP + TCP + + + + http + HTTP + + + + + + #Type + Type + + + + #Request + Request + + + + + #InsertDefaultContent + Insert Default Content + + + + #Response + Response + + + + HTTP + HTTP + + + + + + #Path + Path + + + + WebSocket + WebSocket + + + + + #Headers + Headers + + + + mKCP + mKCP + + + + #MTU + MTU + + + + #TTI (ms) + TTI (ms) + + + + #UplinkCapacity (MB/s) + Uplink Capacity (MB/s) + + + + #Congestion + Congestion Control + + + + #Enabled + Enabled + + + + #DownlinkCapacity (MB/s) + Downlink Capacity (MB/s) + + + + #ReadBufferSize (MB) + Read Buffer Size (MB) + + + + #WriteBufferSize (MB) + Write Buffer Size (MB) + + + + + #Header + Headers + + + + + srtp (SRTP, FaceTime) + srtp (SRTP, FaceTime) + + + + + utp (BitTorrent) + utp (BitTorrent) + + + + + wechat-video (WeChat Video Message) + wechat-video (WeChat Video Message) + + + + + dtls (DTLS 1.2) + dtls (DTLS 1.2) + + + + + wireguard (WireGuard fake packets) + wireguard (WireGuard fake packets) + + + + DomainSocket + DomainSocket + + + + QUIC + QUIC + + + + #Key + Key + + + + ImportConfig + + + OpenConfigFile + Open Config File + + + + #VMessDecodeError + + + + + #NotValidVMessProtocolString + + + + + ImportConfig + Import Config + + + + CannotGenerateConfig + Failed to generate config file + + + + ImportConfigWindow + + + Import file + Import file + + + + #ImportFrom + Import From + + + + Existing File + Existing File + + + + VMess Connection String + VMess Connection String + + + + #FromFile + From file + + + + #Path + Path + + + + #SelectFile + Select File + + + + #Name + Name + + + + #Inbound + Inbound Settings + + + + #UseCurrent + Use Current Settings + + + + #UseImported + Use Imported Inbound Settings + + + + #From VMess Connection String + From VMess Connection String + + + + #VMess Connection String + VMess Connection String + + + + MainWindow + + + + Qv2ray + + + + + + #Start + Start + + + + + #Stop + Stop + + + + + #Restart + Restart + + + + #ClearLog + Clear Log + + + + #HostList + Host List + + + + #ConfigDetail + Detailed Config Info + + + + #Host + Host + + + + #Port + Port + + + + #UUID + UUID + + + + #Transport + Transport Settings + + + + + #ConnectionSettings + Connection Settings + + + + #File + File + + + + #NewConnection + New Connection + + + + #ManuallyInput + Manually Input Config + + + + #ImportConnection + Import Config File + + + + #Exit + Exit + + + + #Preferences + Preferences + + + + + #Hide + Hide + + + + #Quit + Quit + + + + #Show + Show + + + + PrefrencesWindow + + + + + Prefrences + Preferences + + + + #General + General + + + + #Language + Language + + + + zh-CN + + + + + en-US + + + + + #RunAsRoot + Run v2ray as root + + + + + + + + + + #Enabled + Enabled + + + + #LogLevel + Log Level + + + + debug + Debug + + + + info + Info + + + + warning + Warning + + + + error + Error + + + + none + Do not use + + + + #MuxCool + Mux Settings + + + + #Concurrency + Maximum Connections + + + + #InboundSettings + Inbound Settings + + + + HTTP + HTTP + + + + + #Port + Port + + + + 8080 + + + + + + #Username + Username + + + + + #Auth + Authentication + + + + + #Password + Password + + + + SOCKS + SOCKS + + + + 9001 + + + + + PortNumbersCannotBeSame + Port numbers cannot be the same + + + + RunAsRootNotOnWindows + Run as root is not avaliable on Windows Platform + + QObject @@ -29,633 +642,4 @@ Configuration Error - - Ui::ImportConfig - - - OpenConfigFile - Open Config File - - - - ImportConfig - Import Config - - - - CannotGenerateConfig - Failed to generate config file - - - - Ui::MainWindow - - - Qv2ray - - - - - - #Hide - Hide - - - - #Quit - Quit - - - - #Start - Start - - - - #Stop - Stop - - - - #Restart - Restart - - - - #Show - Show - - - - Ui::PrefrencesWindow - - - - Prefrences - Preferences - - - - PortNumbersCannotBeSame - Port numbers cannot be the same - - - - RunAsRootNotOnWindows - Run as root is not avaliable on Windows Platform - - - - WConnectionEdit - - - #ConnectionSettings - Connection Settings - - - - - #Host - Host - - - - #Port - Port - - - - #Name - Name - - - - #UUID - UUID - - - - #AlterID - Alter ID - - - - - #Security - Security Settings - - - - auto - Auto - - - - - aes-128-gcm - aes-128-gcm - - - - - chacha20-poly1305 - chacha20-poly1305 - - - - - - - - none - Do not use - - - - #Transport - Transport Settings - - - - tcp (TCP) - tcp (TCP) - - - - http (HTTP) - http (HTTP) - - - - ws (WebSocket) - ws (WebSocket) - - - - kcp (mKCP) - kcp (mKCP) - - - - domainsocket (Domain Socket) - domainsocket (Domain Socket) - - - - quic (Quick UDP Internet Connection) - quic (Quick UDP Internet Connection) - - - - #TransportSettings - Transport Settings - - - - TCP - TCP - - - - http - HTTP - - - - - - #Type - Type - - - - #Request - Request - - - - - #InsertDefaultContent - Insert Default Content - - - - #Response - Response - - - - HTTP - HTTP - - - - - - #Path - Path - - - - WebSocket - WebSocket - - - - - #Headers - Headers - - - - mKCP - mKCP - - - - #MTU - MTU - - - - #TTI (ms) - TTI (ms) - - - - #UplinkCapacity (MB/s) - Uplink Capacity (MB/s) - - - - #Congestion - Congestion Control - - - - #Enabled - Enabled - - - - #DownlinkCapacity (MB/s) - Downlink Capacity (MB/s) - - - - #ReadBufferSize (MB) - Read Buffer Size (MB) - - - - #WriteBufferSize (MB) - Write Buffer Size (MB) - - - - - #Header - Headers - - - - - srtp (SRTP, FaceTime) - srtp (SRTP, FaceTime) - - - - - utp (BitTorrent) - utp (BitTorrent) - - - - - wechat-video (WeChat Video Message) - wechat-video (WeChat Video Message) - - - - - dtls (DTLS 1.2) - dtls (DTLS 1.2) - - - - - wireguard (WireGuard fake packets) - wireguard (WireGuard fake packets) - - - - DomainSocket - DomainSocket - - - - QUIC - QUIC - - - - #Key - Key - - - - WImportConfig - - - Import file - Import file - - - - #ImportFrom - Import From - - - - Existing File - Existing File - - - - VMess Connection String - VMess Connection String - - - - #FromFile - From file - - - - #Path - Path - - - - #SelectFile - Select File - - - - #Name - Name - - - - #Inbound - Inbound Settings - - - - #UseCurrent - Use Current Settings - - - - #UseImported - Use Imported Inbound Settings - - - - #From VMess Connection String - From VMess Connection String - - - - #VMess Connection String - VMess Connection String - - - - WMain - - - Qv2ray - - - - - #Start - Start - - - - #Stop - Stop - - - - #Restart - Restart - - - - #ClearLog - Clear Log - - - - #HostList - Host List - - - - #ConfigDetail - Detailed Config Info - - - - #Host - Host - - - - #Port - Port - - - - #UUID - UUID - - - - #Transport - Transport Settings - - - - - #ConnectionSettings - Connection Settings - - - - #File - File - - - - #NewConnection - New Connection - - - - #ManuallyInput - Manually Input Config - - - - #ImportConnection - Import Config File - - - - #Exit - Exit - - - - #Preferences - Preferences - - - - WPrefrences - - - Prefrences - Preferences - - - - #General - General - - - - #Language - Language - - - - zh-CN - - - - - en-US - - - - - #RunAsRoot - Run v2ray as root - - - - - - - - - - #Enabled - Enabled - - - - #LogLevel - Log Level - - - - debug - Debug - - - - info - Info - - - - warning - Warning - - - - error - Error - - - - none - Do not use - - - - #MuxCool - Mux Settings - - - - #Concurrency - Maximum Connections - - - - #InboundSettings - Inbound Settings - - - - HTTP - HTTP - - - - - #Port - Port - - - - 8080 - - - - - - #Username - Username - - - - - #Auth - Authentication - - - - - #Password - Password - - - - SOCKS - SOCKS - - - - 9001 - - - diff --git a/translations/zh-CN.ts b/translations/zh-CN.ts index ac79590d..652968aa 100644 --- a/translations/zh-CN.ts +++ b/translations/zh-CN.ts @@ -1,6 +1,619 @@ + + ConnectionEditWindow + + + #ConnectionSettings + 连接设置 + + + + + #Host + 域名 + + + + #Port + 端口 + + + + #Name + 名称 + + + + #UUID + UUID + + + + #AlterID + Alter ID + + + + + #Security + 安全设置 + + + + auto + 自动 + + + + + aes-128-gcm + aes-128-gcm + + + + + chacha20-poly1305 + chacha20-poly1305 + + + + + + + + none + 不使用 + + + + #Transport + 传输设置 + + + + tcp (TCP) + tcp (TCP) + + + + http (HTTP) + http (HTTP) + + + + ws (WebSocket) + ws (WebSocket) + + + + kcp (mKCP) + kcp (mKCP) + + + + domainsocket (Domain Socket) + domainsocket (Domain Socket) + + + + quic (Quick UDP Internet Connection) + quic (Quick UDP Internet Connection) + + + + #TransportSettings + 传输设置 + + + + TCP + TCP + + + + http + HTTP + + + + + + #Type + 类型 + + + + #Request + 请求 + + + + + #InsertDefaultContent + 默认值 + + + + #Response + 相应 + + + + HTTP + HTTP + + + + + + #Path + 路径 + + + + WebSocket + WebSocket + + + + + #Headers + 头伪装 + + + + mKCP + mKCP + + + + #MTU + 最大传输单元 + + + + #TTI (ms) + 传输时间间隔 + + + + #UplinkCapacity (MB/s) + 上行链路容量 (MB/s) + + + + #Congestion + 拥塞控制 + + + + #Enabled + 启用 + + + + #DownlinkCapacity (MB/s) + 下行链路容量 (MB/s) + + + + #ReadBufferSize (MB) + 读取缓冲区大小 (MB) + + + + #WriteBufferSize (MB) + 写入缓冲区大小 (MB) + + + + + #Header + 头伪装 + + + + + srtp (SRTP, FaceTime) + srtp (SRTP, FaceTime) + + + + + utp (BitTorrent) + utp (BitTorrent) + + + + + wechat-video (WeChat Video Message) + wechat-video (WeChat Video Message) + + + + + dtls (DTLS 1.2) + dtls (DTLS 1.2) + + + + + wireguard (WireGuard fake packets) + wireguard (WireGuard fake packets) + + + + DomainSocket + DomainSocket + + + + QUIC + QUIC + + + + #Key + 密钥 + + + + ImportConfig + + + OpenConfigFile + 打开配置文件 + + + + #VMessDecodeError + + + + + #NotValidVMessProtocolString + + + + + ImportConfig + 导入配置 + + + + CannotGenerateConfig + 无法生成配置文件 + + + + ImportConfigWindow + + + Import file + 导入文件 + + + + #ImportFrom + 导入源 + + + + Existing File + 现有文件 + + + + VMess Connection String + VMess 连接字符串 + + + + #FromFile + 从文件 + + + + #Path + 路径 + + + + #SelectFile + 选择文件 + + + + #Name + 名称 + + + + #Inbound + 入站设置 + + + + #UseCurrent + 使用现有设置 + + + + #UseImported + 使用导入的设置 + + + + #From VMess Connection String + 从 VMess 连接字符串 + + + + #VMess Connection String + VMess 连接字符串 + + + + MainWindow + + + + Qv2ray + + + + + + #Start + 启动 + + + + + #Stop + 停止 + + + + + #Restart + 重新启动 + + + + #ClearLog + 清除日志 + + + + #HostList + 服务器列表 + + + + #ConfigDetail + 配置详细信息 + + + + #Host + 域名 + + + + #Port + 端口 + + + + #UUID + UUID + + + + #Transport + 传输设置 + + + + + #ConnectionSettings + 连接设置 + + + + #File + 文件 + + + + #NewConnection + 新建连接 + + + + #ManuallyInput + 手动输入配置 + + + + #ImportConnection + 导入配置文件 + + + + #Exit + 退出 + + + + #Preferences + 首选项 + + + + + #Hide + 隐藏 + + + + #Quit + 退出 + + + + #Show + 显示 + + + + PrefrencesWindow + + + + + Prefrences + 首选项 + + + + #General + 一般 + + + + #Language + 语言 + + + + zh-CN + + + + + en-US + + + + + #RunAsRoot + 使用 root 启动 + + + + + + + + + + #Enabled + 启用 + + + + #LogLevel + 日志等级 + + + + debug + 调试 + + + + info + 信息 + + + + warning + 警告 + + + + error + 错误 + + + + none + 不使用 + + + + #MuxCool + Mux 设置 + + + + #Concurrency + 最大并发连接数 + + + + #InboundSettings + 入站设置 + + + + HTTP + HTTP + + + + + #Port + 端口 + + + + 8080 + + + + + + #Username + 用户名 + + + + + #Auth + 鉴权 + + + + + #Password + 密码 + + + + SOCKS + SOCKS + + + + 9001 + + + + + PortNumbersCannotBeSame + 端口号不能相同 + + + + RunAsRootNotOnWindows + Windows 平台不支持这个选项 + + QObject @@ -29,633 +642,4 @@ 配置出错 - - Ui::ImportConfig - - - OpenConfigFile - 打开配置文件 - - - - ImportConfig - 导入配置 - - - - CannotGenerateConfig - 无法生成配置文件 - - - - Ui::MainWindow - - - Qv2ray - - - - - - #Hide - 隐藏 - - - - #Quit - 退出 - - - - #Start - 启动 - - - - #Stop - 停止 - - - - #Restart - 重新启动 - - - - #Show - 显示 - - - - Ui::PrefrencesWindow - - - - Prefrences - 首选项 - - - - PortNumbersCannotBeSame - 端口号不能相同 - - - - RunAsRootNotOnWindows - Windows 平台不支持这个选项 - - - - WConnectionEdit - - - #ConnectionSettings - 连接设置 - - - - - #Host - 域名 - - - - #Port - 端口 - - - - #Name - 名称 - - - - #UUID - UUID - - - - #AlterID - Alter ID - - - - - #Security - 安全设置 - - - - auto - 自动 - - - - - aes-128-gcm - aes-128-gcm - - - - - chacha20-poly1305 - chacha20-poly1305 - - - - - - - - none - 不使用 - - - - #Transport - 传输设置 - - - - tcp (TCP) - tcp (TCP) - - - - http (HTTP) - http (HTTP) - - - - ws (WebSocket) - ws (WebSocket) - - - - kcp (mKCP) - kcp (mKCP) - - - - domainsocket (Domain Socket) - domainsocket (Domain Socket) - - - - quic (Quick UDP Internet Connection) - quic (Quick UDP Internet Connection) - - - - #TransportSettings - 传输设置 - - - - TCP - TCP - - - - http - HTTP - - - - - - #Type - 类型 - - - - #Request - 请求 - - - - - #InsertDefaultContent - 默认值 - - - - #Response - 相应 - - - - HTTP - HTTP - - - - - - #Path - 路径 - - - - WebSocket - WebSocket - - - - - #Headers - 头伪装 - - - - mKCP - mKCP - - - - #MTU - 最大传输单元 - - - - #TTI (ms) - 传输时间间隔 - - - - #UplinkCapacity (MB/s) - 上行链路容量 (MB/s) - - - - #Congestion - 拥塞控制 - - - - #Enabled - 启用 - - - - #DownlinkCapacity (MB/s) - 下行链路容量 (MB/s) - - - - #ReadBufferSize (MB) - 读取缓冲区大小 (MB) - - - - #WriteBufferSize (MB) - 写入缓冲区大小 (MB) - - - - - #Header - 头伪装 - - - - - srtp (SRTP, FaceTime) - srtp (SRTP, FaceTime) - - - - - utp (BitTorrent) - utp (BitTorrent) - - - - - wechat-video (WeChat Video Message) - wechat-video (WeChat Video Message) - - - - - dtls (DTLS 1.2) - dtls (DTLS 1.2) - - - - - wireguard (WireGuard fake packets) - wireguard (WireGuard fake packets) - - - - DomainSocket - DomainSocket - - - - QUIC - QUIC - - - - #Key - 密钥 - - - - WImportConfig - - - Import file - 导入文件 - - - - #ImportFrom - 导入源 - - - - Existing File - 现有文件 - - - - VMess Connection String - VMess 连接字符串 - - - - #FromFile - 从文件 - - - - #Path - 路径 - - - - #SelectFile - 选择文件 - - - - #Name - 名称 - - - - #Inbound - 入站设置 - - - - #UseCurrent - 使用现有设置 - - - - #UseImported - 使用导入的设置 - - - - #From VMess Connection String - 从 VMess 连接字符串 - - - - #VMess Connection String - VMess 连接字符串 - - - - WMain - - - Qv2ray - - - - - #Start - 启动 - - - - #Stop - 停止 - - - - #Restart - 重新启动 - - - - #ClearLog - 清除日志 - - - - #HostList - 服务器列表 - - - - #ConfigDetail - 配置详细信息 - - - - #Host - 域名 - - - - #Port - 端口 - - - - #UUID - UUID - - - - #Transport - 传输设置 - - - - - #ConnectionSettings - 连接设置 - - - - #File - 文件 - - - - #NewConnection - 新建连接 - - - - #ManuallyInput - 手动输入配置 - - - - #ImportConnection - 导入配置文件 - - - - #Exit - 退出 - - - - #Preferences - 首选项 - - - - WPrefrences - - - Prefrences - 首选项 - - - - #General - 一般 - - - - #Language - 语言 - - - - zh-CN - - - - - en-US - - - - - #RunAsRoot - 使用 root 启动 - - - - - - - - - - #Enabled - 启用 - - - - #LogLevel - 日志等级 - - - - debug - 调试 - - - - info - 信息 - - - - warning - 警告 - - - - error - 错误 - - - - none - 不使用 - - - - #MuxCool - Mux 设置 - - - - #Concurrency - 最大并发连接数 - - - - #InboundSettings - 入站设置 - - - - HTTP - HTTP - - - - - #Port - 端口 - - - - 8080 - - - - - - #Username - 用户名 - - - - - #Auth - 鉴权 - - - - - #Password - 密码 - - - - SOCKS - SOCKS - - - - 9001 - - - diff --git a/utils/vmess2json.py b/utils/vmess2json.py deleted file mode 100755 index de5e450a..00000000 --- a/utils/vmess2json.py +++ /dev/null @@ -1,599 +0,0 @@ -#!/usr/bin/env python3 - -#Imported and modified from "https://github.com/boypt/vmess2json.git", thanks to the author boypt. -import os -import sys -import json -import base64 -import pprint -import argparse -import random -import hashlib -import socket -import urllib.request - -TPL = {} -TPL["CLIENT"] = """ -{ - "log": { - "access": "", - "error": "", - "loglevel": "error" - }, - "inbounds": [ - ], - "outbounds": [ - { - "protocol": "vmess", - "settings": { - "vnext": [ - { - "address": "host.host", - "port": 1234, - "users": [ - { - "email": "user@v2ray.com", - "id": "", - "alterId": 0, - "security": "auto" - } - ] - } - ] - }, - "streamSettings": { - "network": "tcp" - }, - "mux": { - "enabled": true - }, - "tag": "proxy" - }, - { - "protocol": "freedom", - "tag": "direct" - } - ], - "dns": { - "servers": [ - "8.8.8.8", - "8.8.4.4", - "1.1.1.1" - ] - }, - "routing": { - "domainStrategy": "IPIfNonMatch", - "rules": [ - { - "type": "field", - "ip": [ - "geoip:private", - "geoip:cn" - ], - "outboundTag": "direct" - }, - { - "type": "field", - "domain": [ - "geosite:cn" - ], - "outboundTag": "direct" - } - ] - } -} -""" - -# tcpSettings -TPL["http"] = """ -{ - "header": { - "type": "http", - "request": { - "version": "1.1", - "method": "GET", - "path": [ - "/" - ], - "headers": { - "Host": [ - "www.cloudflare.com", - "www.amazon.com" - ], - "User-Agent": [ - "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.75 Safari/537.36", - "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36", - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Safari/537.36", - "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:57.0) Gecko/20100101 Firefox/57.0" - ], - "Accept": [ - "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8" - ], - "Accept-language": [ - "zh-CN,zh;q=0.8,en-US;q=0.6,en;q=0.4" - ], - "Accept-Encoding": [ - "gzip, deflate, br" - ], - "Cache-Control": [ - "no-cache" - ], - "Pragma": "no-cache" - } - } - } -} -""" - -# kcpSettings -TPL["kcp"] = """ -{ - "mtu": 1350, - "tti": 50, - "uplinkCapacity": 12, - "downlinkCapacity": 100, - "congestion": false, - "readBufferSize": 2, - "writeBufferSize": 2, - "header": { - "type": "wechat-video" - } -} -""" - -# wsSettings -TPL["ws"] = """ -{ - "connectionReuse": true, - "path": "/path", - "headers": { - "Host": "host.host.host" - } -} -""" - - -# httpSettings -TPL["h2"] = """ -{ - "host": [ - "host.com" - ], - "path": "/host" -} -""" - -TPL["quic"] = """ -{ - "security": "none", - "key": "", - "header": { - "type": "none" - } -} -""" - -TPL["in_socks"] = """ -{ - "tag":"socks-in", - "port": 10808, - "listen": "::", - "protocol": "socks", - "settings": { - "auth": "noauth", - "udp": true, - "ip": "127.0.0.1" - } -} -""" - -TPL["in_http"] = """ -{ - "tag":"http-in", - "port": 8123, - "listen": "::", - "protocol": "http" -} -""" - -TPL["in_mt"] = """ -{ - "tag": "mt-in", - "port": 6666, - "protocol": "mtproto", - "settings": { - "users": [ - { - "secret": "" - } - ] - } -} -""" - -TPL["out_mt"] = """ -{ - "tag": "mt-out", - "protocol": "mtproto", - "proxySettings": { - "tag": "proxy" - } -} -""" - -TPL["in_dns"] = """ -{ - "port": 53, - "tag": "dns-in", - "protocol": "dokodemo-door", - "settings": { - "address": "1.1.1.1", - "port": 53, - "network": "tcp,udp" - } -} -""" - -TPL["conf_dns"] = """ -{ - "hosts": { - "geosite:category-ads": "127.0.0.1", - "domain:googleapis.cn": "googleapis.com" - }, - "servers": [ - "1.0.0.1", - { - "address": "1.2.4.8", - "domains": [ - "geosite:cn" - ], - "port": 53 - } - ] -} -""" - -TPL["in_tproxy"] = """ -{ - "tag":"tproxy-in", - "port": 1080, - "protocol": "dokodemo-door", - "settings": { - "network": "tcp,udp", - "followRedirect": true - }, - "streamSettings": { - "sockopt": { - "tproxy":"tproxy" - } - }, - "sniffing": { - "enabled": true, - "destOverride": [ - "http", - "tls" - ] - } -} -""" - -TPL["in_api"] = """ -{ - "tag": "api", - "port": 10085, - "listen": "127.0.0.1", - "protocol": "dokodemo-door", - "settings": { - "address": "127.0.0.1" - } -} -""" - -def parseVmess(vmesslink): - """ - return: -{ - "v": "2", - "ps": "remark", - "add": "4.3.2.1", - "port": "1024", - "id": "xxx", - "aid": "64", - "net": "tcp", - "type": "none", - "host": "", - "path": "", - "tls": "" -} - """ - vmscheme = "vmess://" - if vmesslink.startswith(vmscheme): - bs = vmesslink[len(vmscheme):] - #paddings - blen = len(bs) - if blen % 4 > 0: - bs += "=" * (4 - blen % 4) - - vms = base64.b64decode(bs).decode() - return json.loads(vms) - else: - raise Exception("vmess link invalid") - -def load_TPL(stype): - s = TPL[stype] - return json.loads(s) - -def fill_basic(_c, _v): - _outbound = _c["outbounds"][0] - _vnext = _outbound["settings"]["vnext"][0] - - _vnext["address"] = _v["add"] - _vnext["port"] = int(_v["port"]) - _vnext["users"][0]["id"] = _v["id"] - _vnext["users"][0]["alterId"] = int(_v["aid"]) - - _outbound["streamSettings"]["network"] = _v["net"] - - if _v["tls"] == "tls": - _outbound["streamSettings"]["security"] = "tls" - - return _c - -def fill_tcp_http(_c, _v): - tcps = load_TPL("http") - tcps["header"]["type"] = _v["type"] - if _v["host"] != "": - # multiple host - tcps["header"]["request"]["headers"]["Host"] = _v["host"].split(",") - - if _v["path"] != "": - tcps["header"]["request"]["path"] = [ _v["path"] ] - - _c["outbounds"][0]["streamSettings"]["tcpSettings"] = tcps - return _c - -def fill_kcp(_c, _v): - kcps = load_TPL("kcp") - kcps["header"]["type"] = _v["type"] - _c["outbounds"][0]["streamSettings"]["kcpSettings"] = kcps - return _c - -def fill_ws(_c, _v): - wss = load_TPL("ws") - wss["path"] = _v["path"] - wss["headers"]["Host"] = _v["host"] - _c["outbounds"][0]["streamSettings"]["wsSettings"] = wss - return _c - -def fill_h2(_c, _v): - h2s = load_TPL("h2") - h2s["path"] = _v["path"] - h2s["host"] = [ _v["host"] ] - _c["outbounds"][0]["streamSettings"]["httpSettings"] = h2s - return _c - -def fill_quic(_c, _v): - quics = load_TPL("quic") - quics["header"]["type"] = _v["type"] - quics["security"] = _v["host"] - quics["key"] = _v["path"] - _c["outbounds"][0]["streamSettings"]["quicSettings"] = quics - return _c - -def vmess2client(_t, _v): - _c = fill_basic(_t, _v) - - _net = _v["net"] - _type = _v["type"] - - if _net == "kcp": - return fill_kcp(_c, _v) - elif _net == "ws": - return fill_ws(_c, _v) - elif _net == "h2": - return fill_h2(_c, _v) - elif _net == "quic": - return fill_quic(_c, _v) - elif _net == "tcp": - if _type == "http": - return fill_tcp_http(_c, _v) - return _c - else: - pprint.pprint(_v) - raise Exception("this link seem invalid to the script, please report to dev.") - - -def parseMultiple(lines): - def genPath(ps, rand=False): - # add random in case list "ps" share common names - curdir = os.environ.get("PWD", '/tmp/') - rnd = "-{}".format(random.randrange(100)) if rand else "" - name = "{}{}.json".format(vc["ps"], rnd) - return os.path.join(curdir, name) - - for line in lines: - vc = parseVmess(line.strip()) - if int(vc["v"]) != 2: - print("Version mismatched, skiped. This script only supports version 2.") - continue - - cc = vmess2client(load_TPL("CLIENT"), vc) - cc = fillInbounds(cc) - - jsonpath = genPath(vc["ps"]) - while os.path.exists(jsonpath): - jsonpath = genPath(vc["ps"], True) - - print("Wrote: " + jsonpath) - with open(jsonpath, 'w') as f: - jsonDump(cc, f) - -def jsonDump(obj, fobj): - if option.outbound: - json.dump(obj["outbounds"][0], fobj, indent=4) - else: - json.dump(obj, fobj, indent=4) - -def fillInbounds(_c): - _ins = option.inbounds.split(",") - for _in in _ins: - _proto, _port = _in.split(":", 2) - _tplKey = "in_"+_proto - if _tplKey in TPL: - _inobj = load_TPL(_tplKey) - _inobj["port"] = int(_port) - _c["inbounds"].append(_inobj) - - if _proto == "dns": - _c["dns"] = load_TPL("conf_dns") - _c["routing"]["rules"].insert(0, { - "type": "field", - "inboundTag": ["dns-in"], - "outboundTag": "dns-out" - }) - _c["outbounds"].append({ - "protocol": "dns", - "tag": "dns-out" - }) - - elif _proto == "api": - _c["api"] = { - "tag": "api", - "services": [ "HandlerService", "LoggerService", "StatsService" ] - } - _c["stats"] = {} - _c["policy"] = { - "levels": { "0": { "statsUserUplink": True, "statsUserDownlink": True }}, - "system": { "statsInboundUplink": True, "statsInboundDownlink": True } - } - _c["routing"]["rules"].insert(0, { - "type": "field", - "inboundTag": ["api"], - "outboundTag": "api" - }) - - elif _proto == "mt": - _inobj["settings"]["users"][0]["secret"] = \ - option.secret if option.secret != "" else hashlib.md5(str(random.random()).encode()).hexdigest() - _c["outbounds"].append(load_TPL("out_mt")) - _c["routing"]["rules"].insert(0, { - "type": "field", - "inboundTag": ["mt-in"], - "outboundTag": "mt-out" - }) - - else: - print("Error Inbound: " + _in) - - return _c - - -def read_subscribe(sub_url): - print("Reading from subscribe ...") - socket.setdefaulttimeout(10) - with urllib.request.urlopen(sub_url) as response: - _subs = response.read() - return base64.b64decode(_subs).decode().split("\n") - -def select_multiple(lines): - vmesses = [] - for _v in lines: - if _v.startswith("vmess://"): - _vinfo = parseVmess(_v) - vmesses.append({ "ps": "[{ps}] {add}:{port}/{net}".format(**_vinfo), "vm": _v }) - - print("Found {} items.".format(len(vmesses))) - - for i, item in enumerate(vmesses): - print("[{}] - {}".format(i+1, item["ps"])) - - print() - - if not sys.stdin.isatty() and os.path.exists('/dev/tty'): - sys.stdin.close() - sys.stdin = open('/dev/tty', 'r') - - if sys.stdin.isatty(): - sel = input("Choose >>> ") - idx = int(sel) - 1 - elif int(option.select) > -1: - idx = int(option.select) - 1 - else: - raise Exception("Current session cant open a tty to select. Specify the index to --select argument.") - - item = vmesses[idx]["vm"] - - cc = vmess2client(load_TPL("CLIENT"), parseVmess(item)) - cc = fillInbounds(cc) - jsonDump(cc, option.output) - -def main(argv): - sys.argv = ["vmess2json.py"] - for i in argv.split(): - sys.argv.append(i) - parser = argparse.ArgumentParser(description="vmess2json convert vmess link to client json config.") - parser.add_argument('-m', '--multiple', - action="store_true", - default=False, - help="read multiple lines from stdin, " - "each write to a json file named by remark, saving in current dir (PWD).") - parser.add_argument('-s', '--select', - action="store", - const="-1", - nargs='?', - help="use together with -m/--multiple or --subscribe. Select one of the vmess link from inputs. Argument is the index(1,2,3...).") - parser.add_argument('-o', '--output', - type=argparse.FileType('w'), - default=sys.stdout, - help="write output to file. default to stdout") - parser.add_argument('--outbound', - action="store_true", - default=False, - help="only output as an outbound object.") - parser.add_argument('--inbounds', - action="store", - default="socks:1080,http:8123", - help="inbounds usage, default: \"socks:1080,http:8123\". Available proto: socks,http,dns,mt,tproxy") - parser.add_argument('--secret', - action="store", - default="", - help="mtproto secret code. if unsepecified, a random one will be generated.") - parser.add_argument('--subscribe', - action="store", - default="", - help="read from a subscribe url, output a menu to choose from.") - parser.add_argument('vmess', - nargs='?', - help="A vmess:// link. If absent, reads a line from stdin.") - - global option - option = parser.parse_args() - - if option.subscribe != "": - if option.select != "": - select_multiple(read_subscribe(option.subscribe)) - elif option.multiple and not option.select: - parseMultiple(read_subscribe(option.subscribe)) - sys.exit(0) - - if option.multiple and option.select != "": - select_multiple(sys.stdin.readlines()) - elif option.multiple and option.select == "": - parseMultiple(sys.stdin.readlines()) - else: - if option.vmess is None and sys.stdin.isatty(): - parser.print_help() - sys.exit(1) - elif option.vmess is None: - vmess = sys.stdin.readline() - else: - vmess = option.vmess - - vc = parseVmess(vmess.strip()) - if int(vc["v"]) != 2: - print("ERROR: Vmess link version mismatch. This script only supports version 2.") - sys.exit(1) - - cc = vmess2client(load_TPL("CLIENT"), vc) - cc = fillInbounds(cc) - jsonDump(cc, option.output)