[fix] Half done PAC, supported Window Proxy AutoSet, Fixed ImportWindow cancel button bug #69

Former-commit-id: 6eeb48a1fd
This commit is contained in:
Leroy.H.Y 2019-11-25 20:07:12 +08:00
parent 51e73d1462
commit 86c7da4384
10 changed files with 102 additions and 35 deletions

View File

@ -115,11 +115,12 @@ namespace Qv2ray
struct Qv2rayPACConfig { struct Qv2rayPACConfig {
bool usePAC; bool usePAC;
int port; int port;
string proxyIP;
int sourceId; int sourceId;
bool useSocksProxy; bool useSocksProxy;
string fileLocation; string fileLocation;
Qv2rayPACConfig(): fileLocation() { } Qv2rayPACConfig(): fileLocation() { }
XTOSTRUCT(O(usePAC, port, sourceId, useSocksProxy, fileLocation)) XTOSTRUCT(O(usePAC, port, proxyIP, sourceId, useSocksProxy, fileLocation))
}; };
struct Qv2rayInboundsConfig { struct Qv2rayInboundsConfig {
string listenip; string listenip;
@ -146,7 +147,7 @@ namespace Qv2ray
socksUDP = true; socksUDP = true;
setSystemProxy = 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 { struct Qv2rayUIConfig {

View File

@ -34,17 +34,17 @@ namespace Qv2ray
QByteArray QvHttpRequestHelper::syncget(const QString &url) QByteArray QvHttpRequestHelper::syncget(const QString &url)
{ {
this->setUrl(url); this->setUrl(url);
LOG(MODULE_NETWORK, "Using system proxy settings");
accessManager.setProxy(QNetworkProxyFactory::systemProxyForQuery().first());
reply = accessManager.get(request); reply = accessManager.get(request);
connect(reply, &QNetworkReply::finished, this, &QvHttpRequestHelper::onRequestFinished); connect(reply, &QNetworkReply::finished, this, &QvHttpRequestHelper::onRequestFinished);
// //
QEventLoop loop; QEventLoop loop;
connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit); connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
loop.exec(); loop.exec();
QEventLoop loop2;
connect(reply, &QNetworkReply::readyRead, &loop2, &QEventLoop::quit);
loop2.exec();
// Data or timeout? // Data or timeout?
return reply->readAll(); auto data = reply->readAll();
return data;
} }
void QvHttpRequestHelper::get(const QString &url) void QvHttpRequestHelper::get(const QString &url)

View File

@ -11,11 +11,6 @@ namespace Qv2ray
pacServer = new QHttpServer(); pacServer = new QHttpServer();
connect(pacServer, &QHttpServer::newRequest, this, &PACHandler::onNewRequest); connect(pacServer, &QHttpServer::newRequest, this, &PACHandler::onNewRequest);
} }
void PACHandler::SetLocalEndpoint(QString address, ushort port)
{
this->address = address;
this->port = port;
}
PACHandler::~PACHandler() PACHandler::~PACHandler()
{ {
pacServer->close(); pacServer->close();
@ -27,25 +22,45 @@ namespace Qv2ray
} }
void PACHandler::StartListen() 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); pacContent = ConvertGFWToPAC(gfwContent, proxyString);
// //
pacServer->listen(QHostAddress(address), port); auto result = pacServer->listen(QHostAddress(address), static_cast<ushort>(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() void PACHandler::StopServer()
{ {
pacServer->close(); if (isStarted) {
pacServer->close();
delete pacServer;
isStarted = false;
}
} }
void PACHandler::onNewRequest(QHttpRequest *req, QHttpResponse *rsp) 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->method() == QHttpRequest::HTTP_GET) {
// //
if (req->path() == "/pac.txt") { if (req->path() == "/pac") {
rsp->setHeader("Content-Type", "application/javascript; charset=utf-8"); rsp->setHeader("Content-Type", "application/javascript; charset=utf-8");
rsp->writeHead(QHttpResponse::StatusCode::STATUS_OK); rsp->writeHead(QHttpResponse::StatusCode::STATUS_OK);
rsp->end(pacContent.toUtf8()); rsp->end(pacContent.toUtf8());
DEBUG(MODULE_PROXY, "Serving a pac file...")
} else { } else {
rsp->writeHead(QHttpResponse::StatusCode::STATUS_NOT_FOUND); rsp->writeHead(QHttpResponse::StatusCode::STATUS_NOT_FOUND);
rsp->end("NOT FOUND"); rsp->end("NOT FOUND");

View File

@ -13,7 +13,6 @@ namespace Qv2ray
public: public:
explicit PACHandler(); explicit PACHandler();
~PACHandler(); ~PACHandler();
void SetLocalEndpoint(QString address, ushort port);
void SetProxyString(QString proxyString); void SetProxyString(QString proxyString);
void StartListen(); void StartListen();
void StopServer(); void StopServer();
@ -24,9 +23,8 @@ namespace Qv2ray
void onNewRequest(QHttpRequest *request, QHttpResponse *response); void onNewRequest(QHttpRequest *request, QHttpResponse *response);
private: private:
bool isStarted;
QHttpServer *pacServer; QHttpServer *pacServer;
QString address;
ushort port;
QString pacContent; QString pacContent;
QString proxyString; QString proxyString;
}; };

View File

@ -6,7 +6,7 @@
#include <QLocalServer> #include <QLocalServer>
namespace Qv2ray namespace Qv2ray
{ {
namespace Utils namespace Components
{ {
namespace NetSpeedPlugin namespace NetSpeedPlugin
{ {

View File

@ -21,7 +21,7 @@ ImportConfigWindow::ImportConfigWindow(QWidget *parent)
: QDialog(parent) : QDialog(parent)
{ {
setupUi(this); 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) void ImportConfigWindow::on_importSourceCombo_currentIndexChanged(int index)
@ -269,3 +269,8 @@ void ImportConfigWindow::on_connectionEditBtn_clicked()
return; return;
} }
} }
void ImportConfigWindow::on_cancelImportBtn_clicked()
{
reject();
}

View File

@ -27,6 +27,8 @@ class ImportConfigWindow : public QDialog, private Ui::ImportConfigWindow
void on_connectionEditBtn_clicked(); void on_connectionEditBtn_clicked();
void on_cancelImportBtn_clicked();
private: private:
QMap<QString, QString> vmessErrors; QMap<QString, QString> vmessErrors;
}; };

View File

@ -303,6 +303,43 @@ void MainWindow::on_startButton_clicked()
speedTimerId = startTimer(1000); 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 // Set system proxy if necessary
bool isComplex = CheckIsComplexConfig(connectionRoot); bool isComplex = CheckIsComplexConfig(connectionRoot);
@ -310,10 +347,6 @@ void MainWindow::on_startButton_clicked()
if (conf.inboundConfig.setSystemProxy && !isComplex) { if (conf.inboundConfig.setSystemProxy && !isComplex) {
// Is simple config and we will try to set system proxy. // Is simple config and we will try to set system proxy.
LOG(MODULE_UI, "Preparing 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; QString proxyAddress;
bool canSetSystemProxy = true; bool canSetSystemProxy = true;
@ -364,6 +397,7 @@ void MainWindow::on_startButton_clicked()
stopButton->setEnabled(startFlag); stopButton->setEnabled(startFlag);
} }
} }
void MainWindow::on_stopButton_clicked() void MainWindow::on_stopButton_clicked()
{ {
if (vinstance->VCoreStatus != STOPPED) { if (vinstance->VCoreStatus != STOPPED) {
@ -384,6 +418,7 @@ void MainWindow::on_stopButton_clicked()
netspeedLabel->setText("0.00 B/s\r\n0.00 B/s"); netspeedLabel->setText("0.00 B/s\r\n0.00 B/s");
dataamountLabel->setText("0.00 B\r\n0.00 B"); dataamountLabel->setText("0.00 B\r\n0.00 B");
// //
// Who cares the check... (inboundConfig.pacConfig.usePAC)
pacServer->StopServer(); pacServer->StopServer();
ClearSystemProxy(); ClearSystemProxy();
LOG(MODULE_UI, "Stopped successfully.") LOG(MODULE_UI, "Stopped successfully.")

View File

@ -238,7 +238,7 @@ void PrefrencesWindow::on_listenIPTxt_textEdited(const QString &arg1)
{ {
NEEDRESTART NEEDRESTART
CurrentConfig.inboundConfig.listenip = arg1.toStdString(); 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) void PrefrencesWindow::on_httpAuthUsernameTxt_textEdited(const QString &arg1)
@ -430,9 +430,10 @@ void PrefrencesWindow::on_tProxyCheckBox_stateChanged(int arg1)
#else #else
Q_UNUSED(arg1) Q_UNUSED(arg1)
tProxyCheckBox->setChecked(false); // No such tProxy thing on Windows and macOS
// No such uid gid thing on Windows and macOS
QvMessageBox(this, tr("Prefrences"), tr("tProxy is not supported on macOS and Windows")); QvMessageBox(this, tr("Prefrences"), tr("tProxy is not supported on macOS and Windows"));
CurrentConfig.tProxySupport = false;
tProxyCheckBox->setChecked(false);
#endif #endif
} }
void PrefrencesWindow::on_bypassCNCb_stateChanged(int arg1) void PrefrencesWindow::on_bypassCNCb_stateChanged(int arg1)
@ -771,32 +772,32 @@ void PrefrencesWindow::on_pacGoBtn_clicked()
switch (gfwListCB->currentIndex()) { switch (gfwListCB->currentIndex()) {
case 0: case 0:
gfwLocation = "https://raw.githubusercontent.com/gfwlist/gfwlist/master/gfwlist.txt"; gfwLocation = "https://raw.githubusercontent.com/gfwlist/gfwlist/master/gfwlist.txt";
fileContent = request->syncget(gfwLocation); fileContent = QString::fromUtf8(request->syncget(gfwLocation));
break; break;
case 1: case 1:
gfwLocation = "https://pagure.io/gfwlist/raw/master/f/gfwlist.txt"; gfwLocation = "https://pagure.io/gfwlist/raw/master/f/gfwlist.txt";
fileContent = request->syncget(gfwLocation); fileContent = QString::fromUtf8(request->syncget(gfwLocation));
break; break;
case 2: case 2:
gfwLocation = "http://repo.or.cz/gfwlist.git/blob_plain/HEAD:/gfwlist.txt"; gfwLocation = "http://repo.or.cz/gfwlist.git/blob_plain/HEAD:/gfwlist.txt";
fileContent = request->syncget(gfwLocation); fileContent = QString::fromUtf8(request->syncget(gfwLocation));
break; break;
case 3: case 3:
gfwLocation = "https://bitbucket.org/gfwlist/gfwlist/raw/HEAD/gfwlist.txt"; gfwLocation = "https://bitbucket.org/gfwlist/gfwlist/raw/HEAD/gfwlist.txt";
fileContent = request->syncget(gfwLocation); fileContent = QString::fromUtf8(request->syncget(gfwLocation));
break; break;
case 4: case 4:
gfwLocation = "https://gitlab.com/gfwlist/gfwlist/raw/master/gfwlist.txt"; gfwLocation = "https://gitlab.com/gfwlist/gfwlist/raw/master/gfwlist.txt";
fileContent = request->syncget(gfwLocation); fileContent = QString::fromUtf8(request->syncget(gfwLocation));
break; break;
case 5: case 5:
gfwLocation = "https://git.tuxfamily.org/gfwlist/gfwlist.git/plain/gfwlist.txt"; gfwLocation = "https://git.tuxfamily.org/gfwlist/gfwlist.git/plain/gfwlist.txt";
fileContent = request->syncget(gfwLocation); fileContent = QString::fromUtf8(request->syncget(gfwLocation));
break; break;
case 6: case 6:
@ -820,7 +821,7 @@ void PrefrencesWindow::on_pacGoBtn_clicked()
void PrefrencesWindow::on_pacPortSB_valueChanged(int arg1) void PrefrencesWindow::on_pacPortSB_valueChanged(int arg1)
{ {
CurrentConfig.inboundConfig.pacConfig.port = 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) void PrefrencesWindow::on_setSysProxyCB_stateChanged(int arg1)

View File

@ -588,6 +588,16 @@
</item> </item>
</widget> </widget>
</item> </item>
<item row="4" column="1">
<widget class="QLineEdit" name="pacProxyTxt"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_56">
<property name="text">
<string>PAC Proxy IP</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>