mirror of
https://github.com/yuezk/GlobalProtect-openconnect.git
synced 2025-04-02 18:31:50 -04:00
Add a scripting mode to GPClient (#110)
This commit is contained in:
parent
dd81ed9519
commit
9d6ec84c14
2
3rdparty/plog
vendored
2
3rdparty/plog
vendored
@ -1 +1 @@
|
||||
Subproject commit f4c22b03d5d3aa753cca8e716636ac4eb29b0917
|
||||
Subproject commit 914e799d2b08d790f5d04d1c46928586b3a41250
|
@ -33,6 +33,8 @@ add_executable(gpclient
|
||||
gpclient.ui
|
||||
normalloginwindow.ui
|
||||
settingsdialog.ui
|
||||
vpn_dbus.cpp
|
||||
vpn_json.cpp
|
||||
resources.qrc
|
||||
${gpclient_GENERATED_SOURCES}
|
||||
)
|
||||
@ -52,7 +54,7 @@ add_3rdparty(
|
||||
add_3rdparty(
|
||||
plog
|
||||
GIT_REPOSITORY https://github.com/SergiusTheBest/plog.git
|
||||
GIT_TAG 1.1.5
|
||||
GIT_TAG master
|
||||
CMAKE_ARGS
|
||||
-DPLOG_BUILD_SAMPLES=OFF
|
||||
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
|
||||
|
@ -11,9 +11,10 @@
|
||||
|
||||
using namespace gpclient::helper;
|
||||
|
||||
GPClient::GPClient(QWidget *parent)
|
||||
GPClient::GPClient(QWidget *parent, IVpn *vpn)
|
||||
: QMainWindow(parent)
|
||||
, ui(new Ui::GPClient)
|
||||
, vpn(vpn)
|
||||
, settingsDialog(new SettingsDialog(this))
|
||||
{
|
||||
ui->setupUi(this);
|
||||
@ -25,14 +26,14 @@ GPClient::GPClient(QWidget *parent)
|
||||
setupSettings();
|
||||
|
||||
// Restore portal from the previous settings
|
||||
ui->portalInput->setText(settings::get("portal", "").toString());
|
||||
this->portal(settings::get("portal", "").toString());
|
||||
|
||||
// DBus service setup
|
||||
vpn = new com::yuezk::qt::GPService("com.yuezk.qt.GPService", "/", QDBusConnection::systemBus(), this);
|
||||
connect(vpn, &com::yuezk::qt::GPService::connected, this, &GPClient::onVPNConnected);
|
||||
connect(vpn, &com::yuezk::qt::GPService::disconnected, this, &GPClient::onVPNDisconnected);
|
||||
connect(vpn, &com::yuezk::qt::GPService::error, this, &GPClient::onVPNError);
|
||||
connect(vpn, &com::yuezk::qt::GPService::logAvailable, this, &GPClient::onVPNLogAvailable);
|
||||
QObject *ov = dynamic_cast<QObject*>(vpn);
|
||||
connect(ov, SIGNAL(connected()), this, SLOT(onVPNConnected()));
|
||||
connect(ov, SIGNAL(disconnected()), this, SLOT(onVPNDisconnected()));
|
||||
connect(ov, SIGNAL(error(const &QString)), this, SLOT(onVPNError(const QString&)));
|
||||
connect(ov, SIGNAL(logAvailable(const &QString)), this, SLOT(onVPNLogAvailable(const QString&)));
|
||||
|
||||
// Initiallize the context menu of system tray.
|
||||
initSystemTrayIcon();
|
||||
@ -373,7 +374,11 @@ void GPClient::onGatewaySuccess(const QString &authCookie)
|
||||
PLOGI << "Gateway login succeeded, got the cookie " << authCookie;
|
||||
|
||||
isQuickConnect = false;
|
||||
vpn->connect(currentGateway().address(), portalConfig.username(), authCookie, settings::get("extraArgs", "").toString());
|
||||
QList<QString> gatewayAddresses;
|
||||
for (GPGateway &gw : allGateways()) {
|
||||
gatewayAddresses.push_back(gw.address());
|
||||
}
|
||||
vpn->connect(currentGateway().address(), gatewayAddresses, portalConfig.username(), authCookie, settings::get("extraArgs", "").toString());
|
||||
ui->statusLabel->setText("Connecting...");
|
||||
updateConnectionStatus(VpnStatus::pending);
|
||||
}
|
||||
@ -410,6 +415,11 @@ QString GPClient::portal() const
|
||||
return input;
|
||||
}
|
||||
|
||||
void GPClient::portal(QString p)
|
||||
{
|
||||
ui->portalInput->setText(p);
|
||||
}
|
||||
|
||||
bool GPClient::connected() const
|
||||
{
|
||||
const QString statusText = ui->statusLabel->text();
|
||||
|
@ -6,9 +6,9 @@
|
||||
#include <QtWidgets/QMenu>
|
||||
#include <QtWidgets/QPushButton>
|
||||
|
||||
#include "gpserviceinterface.h"
|
||||
#include "portalconfigresponse.h"
|
||||
#include "settingsdialog.h"
|
||||
#include "vpn.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
namespace Ui { class GPClient; }
|
||||
@ -19,12 +19,20 @@ class GPClient : public QMainWindow
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
GPClient(QWidget *parent = nullptr);
|
||||
GPClient(QWidget *parent, IVpn *vpn);
|
||||
~GPClient();
|
||||
|
||||
void activate();
|
||||
void quit();
|
||||
|
||||
QString portal() const;
|
||||
void portal(QString);
|
||||
|
||||
GPGateway currentGateway() const;
|
||||
void setCurrentGateway(const GPGateway gateway);
|
||||
|
||||
void doConnect();
|
||||
|
||||
private slots:
|
||||
void onSettingsButtonClicked();
|
||||
void onSettingsAccepted();
|
||||
@ -58,7 +66,7 @@ private:
|
||||
};
|
||||
|
||||
Ui::GPClient *ui;
|
||||
com::yuezk::qt::GPService *vpn;
|
||||
IVpn *vpn;
|
||||
|
||||
QSystemTrayIcon *systemTrayIcon;
|
||||
QMenu *contextMenu;
|
||||
@ -83,20 +91,15 @@ private:
|
||||
void populateGatewayMenu();
|
||||
void updateConnectionStatus(const VpnStatus &status);
|
||||
|
||||
void doConnect();
|
||||
void portalLogin();
|
||||
void tryGatewayLogin();
|
||||
void gatewayLogin();
|
||||
|
||||
QString portal() const;
|
||||
bool connected() const;
|
||||
|
||||
QList<GPGateway> allGateways() const;
|
||||
void setAllGateways(QList<GPGateway> gateways);
|
||||
|
||||
GPGateway currentGateway() const;
|
||||
void setCurrentGateway(const GPGateway gateway);
|
||||
|
||||
void clearSettings();
|
||||
};
|
||||
#endif // GPCLIENT_H
|
||||
|
@ -3,24 +3,22 @@
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QStandardPaths>
|
||||
#include <plog/Log.h>
|
||||
#include <plog/Init.h>
|
||||
#include <plog/Appenders/ColorConsoleAppender.h>
|
||||
#include <plog/Formatters/TxtFormatter.h>
|
||||
|
||||
#include "singleapplication.h"
|
||||
#include "gpclient.h"
|
||||
#include "vpn_dbus.h"
|
||||
#include "vpn_json.h"
|
||||
#include "enhancedwebview.h"
|
||||
#include "sigwatch.h"
|
||||
#include "version.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
const QDir path = QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation) + "/GlobalProtect-openconnect";
|
||||
const QString logFile = path.path() + "/gpclient.log";
|
||||
if (!path.exists()) {
|
||||
path.mkpath(".");
|
||||
}
|
||||
|
||||
static plog::ColorConsoleAppender<plog::TxtFormatter> consoleAppender;
|
||||
plog::init(plog::debug, logFile.toUtf8()).addAppender(&consoleAppender);
|
||||
plog::ColorConsoleAppender<plog::TxtFormatter> consoleAppender(plog::streamStdErr);
|
||||
plog::init(plog::debug, &consoleAppender);
|
||||
|
||||
PLOGI << "GlobalProtect started, version: " << VERSION;
|
||||
|
||||
@ -33,9 +31,35 @@ int main(int argc, char *argv[])
|
||||
SingleApplication app(argc, argv);
|
||||
app.setQuitOnLastWindowClosed(false);
|
||||
|
||||
GPClient w;
|
||||
QCommandLineParser parser;
|
||||
parser.addHelpOption();
|
||||
parser.addVersionOption();
|
||||
parser.addPositionalArgument("server", "The URL of the VPN server. Optional.");
|
||||
parser.addPositionalArgument("gateway", "The URL of the specific VPN gateway. Optional.");
|
||||
parser.addOptions({
|
||||
{"json", "Write the result of the handshake with the GlobalConnect server to stdout as JSON and terminate. Useful for scripting."},
|
||||
{"now", "Do not show the dialog with the connect button; connect immediately instead."},
|
||||
});
|
||||
parser.process(app);
|
||||
|
||||
const QStringList positional = parser.positionalArguments();
|
||||
|
||||
IVpn *vpn = parser.isSet("json") // yes it leaks, but this is cleared on exit anyway
|
||||
? static_cast<IVpn*>(new VpnJson(nullptr)) // Print to stdout and exit
|
||||
: static_cast<IVpn*>(new VpnDbus(nullptr)); // Contact GPService daemon via dbus
|
||||
GPClient w(nullptr, vpn);
|
||||
w.show();
|
||||
|
||||
if (positional.size() > 0) {
|
||||
w.portal(positional.at(0));
|
||||
}
|
||||
if (positional.size() > 1) {
|
||||
GPGateway gw;
|
||||
gw.setName(positional.at(1));
|
||||
gw.setAddress(positional.at(1));
|
||||
w.setCurrentGateway(gw);
|
||||
}
|
||||
|
||||
QObject::connect(&app, &SingleApplication::instanceStarted, &w, &GPClient::activate);
|
||||
|
||||
UnixSignalWatcher sigwatch;
|
||||
@ -45,5 +69,12 @@ int main(int argc, char *argv[])
|
||||
sigwatch.watchForSignal(SIGHUP);
|
||||
QObject::connect(&sigwatch, &UnixSignalWatcher::unixSignal, &w, &GPClient::quit);
|
||||
|
||||
if (parser.isSet("now")) {
|
||||
w.doConnect();
|
||||
}
|
||||
if (parser.isSet("json")) {
|
||||
QObject::connect(static_cast<VpnJson*>(vpn), &VpnJson::connected, &w, &GPClient::quit);
|
||||
}
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
|
24
GPClient/vpn.h
Normal file
24
GPClient/vpn.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef VPN_H
|
||||
#define VPN_H
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QString>
|
||||
|
||||
class IVpn
|
||||
{
|
||||
public:
|
||||
virtual ~IVpn() = default;
|
||||
|
||||
virtual void connect(const QString &preferredServer, const QList<QString> &servers, const QString &username, const QString &passwd, const QString &extraArgs) = 0;
|
||||
virtual void disconnect() = 0;
|
||||
virtual int status() = 0;
|
||||
|
||||
// signals: // SIGNALS
|
||||
// virtual void connected();
|
||||
// virtual void disconnected();
|
||||
// virtual void error(const QString &errorMessage);
|
||||
// virtual void logAvailable(const QString &log);
|
||||
};
|
||||
|
||||
Q_DECLARE_INTERFACE(IVpn, "IVpn") // define this out of namespace scope
|
||||
|
||||
#endif
|
13
GPClient/vpn_dbus.cpp
Normal file
13
GPClient/vpn_dbus.cpp
Normal file
@ -0,0 +1,13 @@
|
||||
#include "vpn_dbus.h"
|
||||
|
||||
void VpnDbus::connect(const QString &preferredServer, const QList<QString> &servers, const QString &username, const QString &passwd, const QString &extraArgs) {
|
||||
inner->connect(preferredServer, username, passwd, extraArgs);
|
||||
}
|
||||
|
||||
void VpnDbus::disconnect() {
|
||||
inner->disconnect();
|
||||
}
|
||||
|
||||
int VpnDbus::status() {
|
||||
return inner->status();
|
||||
}
|
33
GPClient/vpn_dbus.h
Normal file
33
GPClient/vpn_dbus.h
Normal file
@ -0,0 +1,33 @@
|
||||
#ifndef VPN_DBUS_H
|
||||
#define VPN_DBUS_H
|
||||
#include "vpn.h"
|
||||
#include "gpserviceinterface.h"
|
||||
|
||||
class VpnDbus : public QObject, public IVpn
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(IVpn)
|
||||
|
||||
private:
|
||||
com::yuezk::qt::GPService *inner;
|
||||
|
||||
public:
|
||||
VpnDbus(QObject *parent) : QObject(parent) {
|
||||
inner = new com::yuezk::qt::GPService("com.yuezk.qt.GPService", "/", QDBusConnection::systemBus(), this);
|
||||
QObject::connect(inner, &com::yuezk::qt::GPService::connected, this, &VpnDbus::connected);
|
||||
QObject::connect(inner, &com::yuezk::qt::GPService::disconnected, this, &VpnDbus::disconnected);
|
||||
QObject::connect(inner, &com::yuezk::qt::GPService::error, this, &VpnDbus::error);
|
||||
QObject::connect(inner, &com::yuezk::qt::GPService::logAvailable, this, &VpnDbus::logAvailable);
|
||||
}
|
||||
|
||||
void connect(const QString &preferredServer, const QList<QString> &servers, const QString &username, const QString &passwd, const QString &extraArgs);
|
||||
void disconnect();
|
||||
int status();
|
||||
|
||||
signals: // SIGNALS
|
||||
void connected();
|
||||
void disconnected();
|
||||
void error(const QString &errorMessage);
|
||||
void logAvailable(const QString &log);
|
||||
};
|
||||
#endif
|
24
GPClient/vpn_json.cpp
Normal file
24
GPClient/vpn_json.cpp
Normal file
@ -0,0 +1,24 @@
|
||||
#include "vpn_json.h"
|
||||
#include <QTextStream>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
|
||||
void VpnJson::connect(const QString &preferredServer, const QList<QString> &servers, const QString &username, const QString &passwd, const QString &extraArgs) {
|
||||
QJsonArray sl;
|
||||
for (const QString &srv : servers) {
|
||||
sl.push_back(QJsonValue(srv));
|
||||
}
|
||||
QJsonObject j;
|
||||
j["server"] = preferredServer;
|
||||
j["availableServers"] = sl;
|
||||
j["cookie"] = passwd;
|
||||
QTextStream(stdout) << QJsonDocument(j).toJson(QJsonDocument::Compact) << "\n";
|
||||
emit connected();
|
||||
}
|
||||
|
||||
void VpnJson::disconnect() { /* nop */ }
|
||||
|
||||
int VpnJson::status() {
|
||||
return 4; // disconnected
|
||||
}
|
23
GPClient/vpn_json.h
Normal file
23
GPClient/vpn_json.h
Normal file
@ -0,0 +1,23 @@
|
||||
#ifndef VPN_JSON_H
|
||||
#define VPN_JSON_H
|
||||
#include "vpn.h"
|
||||
|
||||
class VpnJson : public QObject, public IVpn
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(IVpn)
|
||||
|
||||
public:
|
||||
VpnJson(QObject *parent) : QObject(parent) {}
|
||||
|
||||
void connect(const QString &preferredServer, const QList<QString> &servers, const QString &username, const QString &passwd, const QString &extraArgs);
|
||||
void disconnect();
|
||||
int status();
|
||||
|
||||
signals: // SIGNALS
|
||||
void connected();
|
||||
void disconnected();
|
||||
void error(const QString &errorMessage);
|
||||
void logAvailable(const QString &log);
|
||||
};
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user