diff --git a/src/Qv2rayBase.hpp b/src/Qv2rayBase.hpp index fc5efa2c..c9b18bc3 100644 --- a/src/Qv2rayBase.hpp +++ b/src/Qv2rayBase.hpp @@ -115,11 +115,12 @@ namespace Qv2ray struct Qv2rayPACConfig { bool usePAC; int port; + string proxyIP; int sourceId; bool useSocksProxy; string fileLocation; Qv2rayPACConfig(): fileLocation() { } - XTOSTRUCT(O(usePAC, port, sourceId, useSocksProxy, fileLocation)) + XTOSTRUCT(O(usePAC, port, proxyIP, sourceId, useSocksProxy, fileLocation)) }; struct Qv2rayInboundsConfig { string listenip; @@ -146,7 +147,7 @@ namespace Qv2ray socksUDP = true; setSystemProxy = true; } - XTOSTRUCT(O(pacConfig, listenip, socks_port, socks_useAuth, socksAccount, socksUDP, socksLocalIP, http_port, http_useAuth, httpAccount)) + XTOSTRUCT(O(setSystemProxy, pacConfig, listenip, socks_port, socks_useAuth, socksAccount, socksUDP, socksLocalIP, http_port, http_useAuth, httpAccount)) }; struct Qv2rayUIConfig { diff --git a/src/components/QvHTTPRequestHelper.cpp b/src/components/QvHTTPRequestHelper.cpp index 6cf28a69..4f26456f 100644 --- a/src/components/QvHTTPRequestHelper.cpp +++ b/src/components/QvHTTPRequestHelper.cpp @@ -34,17 +34,17 @@ namespace Qv2ray QByteArray QvHttpRequestHelper::syncget(const QString &url) { this->setUrl(url); + LOG(MODULE_NETWORK, "Using system proxy settings"); + accessManager.setProxy(QNetworkProxyFactory::systemProxyForQuery().first()); reply = accessManager.get(request); connect(reply, &QNetworkReply::finished, this, &QvHttpRequestHelper::onRequestFinished); // QEventLoop loop; connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit); loop.exec(); - QEventLoop loop2; - connect(reply, &QNetworkReply::readyRead, &loop2, &QEventLoop::quit); - loop2.exec(); // Data or timeout? - return reply->readAll(); + auto data = reply->readAll(); + return data; } void QvHttpRequestHelper::get(const QString &url) diff --git a/src/components/QvPACHandler.cpp b/src/components/QvPACHandler.cpp index d4aeabaa..926db4e9 100644 --- a/src/components/QvPACHandler.cpp +++ b/src/components/QvPACHandler.cpp @@ -11,11 +11,6 @@ namespace Qv2ray pacServer = new QHttpServer(); connect(pacServer, &QHttpServer::newRequest, this, &PACHandler::onNewRequest); } - void PACHandler::SetLocalEndpoint(QString address, ushort port) - { - this->address = address; - this->port = port; - } PACHandler::~PACHandler() { pacServer->close(); @@ -27,25 +22,45 @@ namespace Qv2ray } void PACHandler::StartListen() { - QString gfwContent = StringFromFile(new QFile(gfwFilePath)); + pacServer = new QHttpServer(); + connect(pacServer, &QHttpServer::newRequest, this, &PACHandler::onNewRequest); + // + auto conf = GetGlobalConfig(); + auto address = QSTRING(conf.inboundConfig.listenip); + auto port = conf.inboundConfig.pacConfig.port; + // + QString gfwContent = StringFromFile(new QFile(QV2RAY_RULES_GFWLIST_PATH)); pacContent = ConvertGFWToPAC(gfwContent, proxyString); // - pacServer->listen(QHostAddress(address), port); + auto result = pacServer->listen(QHostAddress(address), static_cast(port)); + + if (result) { + isStarted = true; + LOG(MODULE_PROXY, "Started PAC listener") + } else { + LOG(MODULE_PROXY, "Failed to listen on port " + to_string(port) + ", please verify the permission.") + QvMessageBox(nullptr, tr("PAC Handler"), tr("Failed to listen PAC request on this port, please verify the permissions")); + } } void PACHandler::StopServer() { - pacServer->close(); + if (isStarted) { + pacServer->close(); + delete pacServer; + isStarted = false; + } } void PACHandler::onNewRequest(QHttpRequest *req, QHttpResponse *rsp) { - rsp->setHeader("Server", "Qv2ray/" QV2RAY_VERSION_STRING " PAC Handler"); + rsp->setHeader("Server", "Qv2ray/" QV2RAY_VERSION_STRING " PAC_Handler"); if (req->method() == QHttpRequest::HTTP_GET) { // - if (req->path() == "/pac.txt") { + if (req->path() == "/pac") { rsp->setHeader("Content-Type", "application/javascript; charset=utf-8"); rsp->writeHead(QHttpResponse::StatusCode::STATUS_OK); rsp->end(pacContent.toUtf8()); + DEBUG(MODULE_PROXY, "Serving a pac file...") } else { rsp->writeHead(QHttpResponse::StatusCode::STATUS_NOT_FOUND); rsp->end("NOT FOUND"); diff --git a/src/components/QvPACHandler.hpp b/src/components/QvPACHandler.hpp index c360f516..d5bcc463 100644 --- a/src/components/QvPACHandler.hpp +++ b/src/components/QvPACHandler.hpp @@ -13,7 +13,6 @@ namespace Qv2ray public: explicit PACHandler(); ~PACHandler(); - void SetLocalEndpoint(QString address, ushort port); void SetProxyString(QString proxyString); void StartListen(); void StopServer(); @@ -24,9 +23,8 @@ namespace Qv2ray void onNewRequest(QHttpRequest *request, QHttpResponse *response); private: + bool isStarted; QHttpServer *pacServer; - QString address; - ushort port; QString pacContent; QString proxyString; }; diff --git a/src/ui/NetSpeedBar/QvNetSpeedBar_linux.cpp b/src/ui/NetSpeedBar/QvNetSpeedBar_linux.cpp index 6c77f4af..12d375e0 100644 --- a/src/ui/NetSpeedBar/QvNetSpeedBar_linux.cpp +++ b/src/ui/NetSpeedBar/QvNetSpeedBar_linux.cpp @@ -6,7 +6,7 @@ #include namespace Qv2ray { - namespace Utils + namespace Components { namespace NetSpeedPlugin { diff --git a/src/ui/w_ImportConfig.cpp b/src/ui/w_ImportConfig.cpp index 06acb6a3..d9e7df28 100644 --- a/src/ui/w_ImportConfig.cpp +++ b/src/ui/w_ImportConfig.cpp @@ -21,7 +21,7 @@ ImportConfigWindow::ImportConfigWindow(QWidget *parent) : QDialog(parent) { setupUi(this); - nameTxt->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd_hh-mm-ss") + "_imported"); + nameTxt->setText(QDateTime::currentDateTime().toString("MM-dd_hh-mm") + "_" + tr("Imported") + "_"); } void ImportConfigWindow::on_importSourceCombo_currentIndexChanged(int index) @@ -269,3 +269,8 @@ void ImportConfigWindow::on_connectionEditBtn_clicked() return; } } + +void ImportConfigWindow::on_cancelImportBtn_clicked() +{ + reject(); +} diff --git a/src/ui/w_ImportConfig.hpp b/src/ui/w_ImportConfig.hpp index 315ddffc..64fa0bfd 100644 --- a/src/ui/w_ImportConfig.hpp +++ b/src/ui/w_ImportConfig.hpp @@ -27,6 +27,8 @@ class ImportConfigWindow : public QDialog, private Ui::ImportConfigWindow void on_connectionEditBtn_clicked(); + void on_cancelImportBtn_clicked(); + private: QMap vmessErrors; }; diff --git a/src/ui/w_MainWindow.cpp b/src/ui/w_MainWindow.cpp index 7dbfa4f1..a4ef6cf2 100644 --- a/src/ui/w_MainWindow.cpp +++ b/src/ui/w_MainWindow.cpp @@ -303,6 +303,43 @@ void MainWindow::on_startButton_clicked() speedTimerId = startTimer(1000); } + bool usePAC = conf.inboundConfig.pacConfig.usePAC; + bool pacUseSocks = conf.inboundConfig.pacConfig.useSocksProxy; + bool httpEnabled = conf.inboundConfig.http_port != 0; + bool socksEnabled = conf.inboundConfig.socks_port != 0; + + // TODO: Set PAC proxy string + + if (usePAC) { + bool canStartPAC = true; + QString pacProxyString; // Something like this --> SOCKS5 127.0.0.1:1080; SOCKS 127.0.0.1:1080; DIRECT; http://proxy:8080 + + if (pacUseSocks) { + if (socksEnabled) { + pacProxyString = "SOCKS5 " + QSTRING(conf.inboundConfig.pacConfig.proxyIP) + ":" + QString::number(conf.inboundConfig.socks_port); + } else { + LOG(MODULE_UI, "PAC is using SOCKS, but it is not enabled") + QvMessageBox(this, tr("Configuring PAC"), tr("Could not start PAC server as it is configured to use SOCKS, but it is not enabled")); + canStartPAC = false; + } + } else { + if (httpEnabled) { + pacProxyString = "http://" + QSTRING(conf.inboundConfig.pacConfig.proxyIP) + ":" + QString::number(conf.inboundConfig.http_port); + } else { + LOG(MODULE_UI, "PAC is using HTTP, but it is not enabled") + QvMessageBox(this, tr("Configuring PAC"), tr("Could not start PAC server as it is configured to use HTTP, but it is not enabled")); + canStartPAC = false; + } + } + + if (canStartPAC) { + pacServer->SetProxyString(pacProxyString); + pacServer->StartListen(); + } else { + LOG(MODULE_PROXY, "Not starting PAC due to previous error.") + } + } + // // Set system proxy if necessary bool isComplex = CheckIsComplexConfig(connectionRoot); @@ -310,10 +347,6 @@ void MainWindow::on_startButton_clicked() if (conf.inboundConfig.setSystemProxy && !isComplex) { // Is simple config and we will try to set system proxy. LOG(MODULE_UI, "Preparing to set system proxy") - bool usePAC = conf.inboundConfig.pacConfig.usePAC; - bool pacUseSocks = conf.inboundConfig.pacConfig.useSocksProxy; - bool httpEnabled = conf.inboundConfig.http_port != 0; - bool socksEnabled = conf.inboundConfig.socks_port != 0; // QString proxyAddress; bool canSetSystemProxy = true; @@ -364,6 +397,7 @@ void MainWindow::on_startButton_clicked() stopButton->setEnabled(startFlag); } } + void MainWindow::on_stopButton_clicked() { if (vinstance->VCoreStatus != STOPPED) { @@ -384,6 +418,7 @@ void MainWindow::on_stopButton_clicked() netspeedLabel->setText("0.00 B/s\r\n0.00 B/s"); dataamountLabel->setText("0.00 B\r\n0.00 B"); // + // Who cares the check... (inboundConfig.pacConfig.usePAC) pacServer->StopServer(); ClearSystemProxy(); LOG(MODULE_UI, "Stopped successfully.") diff --git a/src/ui/w_PrefrencesWindow.cpp b/src/ui/w_PrefrencesWindow.cpp index 233c08bb..c0d9a2b6 100644 --- a/src/ui/w_PrefrencesWindow.cpp +++ b/src/ui/w_PrefrencesWindow.cpp @@ -238,7 +238,7 @@ void PrefrencesWindow::on_listenIPTxt_textEdited(const QString &arg1) { NEEDRESTART CurrentConfig.inboundConfig.listenip = arg1.toStdString(); - //pacAccessPathTxt->setText("http://" + arg1 + ":" + QString::number(pacPortSB->value()) + "/pac.txt"); + //pacAccessPathTxt->setText("http://" + arg1 + ":" + QString::number(pacPortSB->value()) + "/pac"); } void PrefrencesWindow::on_httpAuthUsernameTxt_textEdited(const QString &arg1) @@ -430,9 +430,10 @@ void PrefrencesWindow::on_tProxyCheckBox_stateChanged(int arg1) #else Q_UNUSED(arg1) - tProxyCheckBox->setChecked(false); - // No such uid gid thing on Windows and macOS + // No such tProxy thing on Windows and macOS QvMessageBox(this, tr("Prefrences"), tr("tProxy is not supported on macOS and Windows")); + CurrentConfig.tProxySupport = false; + tProxyCheckBox->setChecked(false); #endif } void PrefrencesWindow::on_bypassCNCb_stateChanged(int arg1) @@ -771,32 +772,32 @@ void PrefrencesWindow::on_pacGoBtn_clicked() switch (gfwListCB->currentIndex()) { case 0: gfwLocation = "https://raw.githubusercontent.com/gfwlist/gfwlist/master/gfwlist.txt"; - fileContent = request->syncget(gfwLocation); + fileContent = QString::fromUtf8(request->syncget(gfwLocation)); break; case 1: gfwLocation = "https://pagure.io/gfwlist/raw/master/f/gfwlist.txt"; - fileContent = request->syncget(gfwLocation); + fileContent = QString::fromUtf8(request->syncget(gfwLocation)); break; case 2: gfwLocation = "http://repo.or.cz/gfwlist.git/blob_plain/HEAD:/gfwlist.txt"; - fileContent = request->syncget(gfwLocation); + fileContent = QString::fromUtf8(request->syncget(gfwLocation)); break; case 3: gfwLocation = "https://bitbucket.org/gfwlist/gfwlist/raw/HEAD/gfwlist.txt"; - fileContent = request->syncget(gfwLocation); + fileContent = QString::fromUtf8(request->syncget(gfwLocation)); break; case 4: gfwLocation = "https://gitlab.com/gfwlist/gfwlist/raw/master/gfwlist.txt"; - fileContent = request->syncget(gfwLocation); + fileContent = QString::fromUtf8(request->syncget(gfwLocation)); break; case 5: gfwLocation = "https://git.tuxfamily.org/gfwlist/gfwlist.git/plain/gfwlist.txt"; - fileContent = request->syncget(gfwLocation); + fileContent = QString::fromUtf8(request->syncget(gfwLocation)); break; case 6: @@ -820,7 +821,7 @@ void PrefrencesWindow::on_pacGoBtn_clicked() void PrefrencesWindow::on_pacPortSB_valueChanged(int arg1) { CurrentConfig.inboundConfig.pacConfig.port = arg1; - //pacAccessPathTxt->setText("http://" + listenIPTxt->text() + ":" + QString::number(arg1) + "/pac.txt"); + //pacAccessPathTxt->setText("http://" + listenIPTxt->text() + ":" + QString::number(arg1) + "/pac"); } void PrefrencesWindow::on_setSysProxyCB_stateChanged(int arg1) diff --git a/src/ui/w_PrefrencesWindow.ui b/src/ui/w_PrefrencesWindow.ui index f048af3f..3f78b9bd 100644 --- a/src/ui/w_PrefrencesWindow.ui +++ b/src/ui/w_PrefrencesWindow.ui @@ -588,6 +588,16 @@ + + + + + + + PAC Proxy IP + + +