Compare commits

..

28 Commits

Author SHA1 Message Date
Kevin Yue
84f1480653 release 1.3.1 2021-08-31 20:54:04 +08:00
Kevin Yue
3175855122 add rpm packaging (#83) 2021-08-31 20:52:08 +08:00
Kevin Yue
fa8b5c1528 Update CI scripts 2021-08-29 20:06:13 +08:00
Kevin Yue
7b9942c7e6 Update README.md 2021-08-26 00:42:25 +08:00
Kevin Yue
011a1a0dec Update README.md 2021-08-26 00:39:13 +08:00
Kevin Yue
4a53033023 [ci] use action-automatic-releases 2021-08-23 08:53:41 +08:00
Kevin Yue
9c6ea1c4b5 [ci] replace artifacts 2021-08-23 08:32:12 +08:00
Kevin Yue
3369ad4c1d [ci] update release action 2021-08-23 08:13:01 +08:00
Kevin Yue
25c9f2291a Update pre-release.yml 2021-08-23 01:35:12 +08:00
Kevin Yue
bba3bc7e4f [ci] improve action script 2021-08-23 01:04:17 +08:00
Kevin Yue
b12b692090 [ci] update action script 2021-08-23 00:30:01 +08:00
Kevin Yue
1300a0cc43 [ci] install qt 2021-08-22 23:56:05 +08:00
Kevin Yue
165080b476 [ci] build debian package 2021-08-22 23:46:20 +08:00
Kevin Yue
d6af8a1598 [ci] Update the changlog 2021-08-22 22:41:47 +08:00
Kevin Yue
eef92b1d31 Update action script 2021-08-22 21:07:52 +08:00
Kevin Yue
946ead24a4 Bump the changelog 2021-08-22 20:05:59 +08:00
Kevin Yue
39e57c8598 Add version suffix 2021-08-22 19:30:34 +08:00
Kevin Yue
4e2e423c27 Update the branch 2021-08-22 18:39:31 +08:00
Kevin Yue
732a62f1ee Add pre-release action 2021-08-22 18:34:56 +08:00
Kevin Yue
9f9444a72b Display error when OpenConnect was not found (#81) 2021-08-21 19:32:13 +08:00
Kevin Yue
6352e1fb2b Make the clientos configurable and improve Reset Settings (#80)
* Set the gateway

* Make clientos configurable

* Update readme.md

* Update README.md
2021-08-21 18:44:16 +08:00
Kevin Yue
42cae3ff26 Port the splitCommand method (#79) 2021-08-19 19:10:05 +08:00
Kevin Yue
53c8572cf6 Update main.yml 2021-08-19 18:42:26 +08:00
Kevin Yue
3f6467321f Update main.yml 2021-08-19 18:33:01 +08:00
Kevin Yue
563ec48c8c Update main.yml 2021-08-19 18:26:05 +08:00
Kevin Yue
3787ae164c Update main.yml 2021-08-19 18:24:30 +08:00
Kevin Yue
04a24c34e8 Update future plan 2021-08-18 16:16:52 +08:00
Kevin Yue
fe68248b1f Add future plan 2021-08-18 16:03:08 +08:00
30 changed files with 415 additions and 59 deletions

View File

@@ -1,4 +1,4 @@
name: CI
name: Build
on:
push:
@@ -16,7 +16,7 @@ jobs:
- name: Install Qt
uses: jurplel/install-qt-action@v2
with:
version: '5.15.2'
version: 5.12.11
modules: 'qtwebengine qtwebsockets'
# Checkout repository and submodules

63
.github/workflows/pre-release.yml vendored Normal file
View File

@@ -0,0 +1,63 @@
name: Pre Release
on:
workflow_run:
workflows: ["Build"]
branches: [master]
types: [completed]
jobs:
pre-release:
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion == 'success' }}
env:
DEBFULLNAME: "Kevin Yue"
DEBEMAIL: "yuezk001@gmail.com"
steps:
# Checkout repository and submodules
- uses: actions/checkout@v2
with:
submodules: recursive
fetch-depth: 0
- name: Init variables
id: vars
run: |
TAG=$(git tag --sort=-v:refname --list "v[0-9]*" | head -n 1 | cut -c 2-)
echo ::set-output name=VERSION::"${TAG}+SNAPSHOT$(date -u +"%Y%m%d%H%M%S")"
echo ::set-output name=TAG::${TAG}
- name: Update debian/changelog
run: |
sudo apt install devscripts
git log --format="%s" v${{ steps.vars.outputs.TAG }}.. | xargs -L1 dch -v ${{ steps.vars.outputs.VERSION }}-1ppa1
- name: "Archive all"
run: |
python -m pip install --upgrade pip
pip install git-archive-all
git-archive-all \
--force-submodules \
--prefix=globalprotect-openconnect-${{ steps.vars.outputs.VERSION }}/ \
./globalprotect-openconnect-${{ steps.vars.outputs.VERSION }}.full.tar.gz
- name: "Debian Packaging"
run: |
sudo apt update
sudo apt install qtbase5-dev libqt5websockets5-dev qtwebengine5-dev qttools5-dev debhelper
mkdir build-debian && cd build-debian
cp ../*.tar.gz globalprotect-openconnect_${{ steps.vars.outputs.VERSION }}.orig.tar.gz
tar xf *.tar.gz
cd globalprotect-openconnect-${{ steps.vars.outputs.VERSION }}
fakeroot dpkg-buildpackage -uc -us -sa
- uses: "marvinpinto/action-automatic-releases@latest"
with:
repo_token: "${{ secrets.GITHUB_TOKEN }}"
automatic_release_tag: "latest"
prerelease: true
title: "globalprotect-openconnect_${{ steps.vars.outputs.VERSION }}"
files: |
*.tar.gz
build-debian/*.deb

View File

@@ -11,7 +11,7 @@ jobs:
- name: Install Qt
uses: jurplel/install-qt-action@v2
with:
version: 5.15.2
version: 5.12.11
modules: 'qtwebengine qtwebsockets'
# Checkout repository and submodules

5
.gitignore vendored
View File

@@ -2,6 +2,11 @@
gpclient
gpservice
*.rpm
*.gz
.DS_Store
build-debian
# Auto generated DBus files
*_adaptor.cpp
*_adaptor.h

View File

@@ -26,6 +26,7 @@ SOURCES += \
cdpcommandmanager.cpp \
enhancedwebview.cpp \
gatewayauthenticator.cpp \
gatewayauthenticatorparams.cpp \
gpgateway.cpp \
gphelper.cpp \
loginparams.cpp \
@@ -43,6 +44,7 @@ HEADERS += \
cdpcommandmanager.h \
enhancedwebview.h \
gatewayauthenticator.h \
gatewayauthenticatorparams.h \
gpgateway.h \
gphelper.h \
loginparams.h \

View File

@@ -8,12 +8,16 @@
using namespace gpclient::helper;
GatewayAuthenticator::GatewayAuthenticator(const QString& gateway, const PortalConfigResponse& portalConfig)
GatewayAuthenticator::GatewayAuthenticator(const QString& gateway, const GatewayAuthenticatorParams& params)
: QObject()
, preloginUrl("https://" + gateway + "/ssl-vpn/prelogin.esp?tmp=tmp&kerberos-support=yes&ipv6-support=yes&clientVer=4100&clientos=Linux")
, gateway(gateway)
, params(params)
, preloginUrl("https://" + gateway + "/ssl-vpn/prelogin.esp?tmp=tmp&kerberos-support=yes&ipv6-support=yes&clientVer=4100")
, loginUrl("https://" + gateway + "/ssl-vpn/login.esp")
, portalConfig(portalConfig)
{
if (!params.clientos().isEmpty()) {
preloginUrl = preloginUrl + "&clientos=" + params.clientos();
}
}
GatewayAuthenticator::~GatewayAuthenticator()
@@ -25,12 +29,16 @@ void GatewayAuthenticator::authenticate()
{
PLOGI << "Start gateway authentication...";
LoginParams params;
params.setUser(portalConfig.username());
params.setPassword(portalConfig.password());
params.setUserAuthCookie(portalConfig.userAuthCookie());
LoginParams loginParams;
loginParams.setUser(params.username());
loginParams.setPassword(params.password());
loginParams.setUserAuthCookie(params.userAuthCookie());
login(params);
if (!params.clientos().isEmpty()) {
loginParams.setClientos(params.clientos());
}
login(loginParams);
}
void GatewayAuthenticator::login(const LoginParams &params)

View File

@@ -1,16 +1,16 @@
#ifndef GATEWAYAUTHENTICATOR_H
#define GATEWAYAUTHENTICATOR_H
#include "portalconfigresponse.h"
#include "normalloginwindow.h"
#include "loginparams.h"
#include "gatewayauthenticatorparams.h"
#include <QObject>
class GatewayAuthenticator : public QObject
{
Q_OBJECT
public:
explicit GatewayAuthenticator(const QString& gateway, const PortalConfigResponse& portalConfig);
explicit GatewayAuthenticator(const QString& gateway, const GatewayAuthenticatorParams& params);
~GatewayAuthenticator();
void authenticate();
@@ -30,11 +30,10 @@ private slots:
private:
QString gateway;
const GatewayAuthenticatorParams& params;
QString preloginUrl;
QString loginUrl;
const PortalConfigResponse& portalConfig;
NormalLoginWindow *normalLoginWindow{ nullptr };
void login(const LoginParams& params);

View File

@@ -0,0 +1,57 @@
#include "gatewayauthenticatorparams.h"
GatewayAuthenticatorParams::GatewayAuthenticatorParams()
{
}
GatewayAuthenticatorParams GatewayAuthenticatorParams::fromPortalConfigResponse(const PortalConfigResponse &portalConfig)
{
GatewayAuthenticatorParams params;
params.setUsername(portalConfig.username());
params.setPassword(portalConfig.password());
params.setUserAuthCookie(portalConfig.userAuthCookie());
return params;
}
const QString &GatewayAuthenticatorParams::username() const
{
return m_username;
}
void GatewayAuthenticatorParams::setUsername(const QString &newUsername)
{
m_username = newUsername;
}
const QString &GatewayAuthenticatorParams::password() const
{
return m_password;
}
void GatewayAuthenticatorParams::setPassword(const QString &newPassword)
{
m_password = newPassword;
}
const QString &GatewayAuthenticatorParams::userAuthCookie() const
{
return m_userAuthCookie;
}
void GatewayAuthenticatorParams::setUserAuthCookie(const QString &newUserAuthCookie)
{
m_userAuthCookie = newUserAuthCookie;
}
const QString &GatewayAuthenticatorParams::clientos() const
{
return m_clientos;
}
void GatewayAuthenticatorParams::setClientos(const QString &newClientos)
{
m_clientos = newClientos;
}

View File

@@ -0,0 +1,33 @@
#ifndef GATEWAYAUTHENTICATORPARAMS_H
#define GATEWAYAUTHENTICATORPARAMS_H
#include <QString>
#include "portalconfigresponse.h"
class GatewayAuthenticatorParams
{
public:
GatewayAuthenticatorParams();
static GatewayAuthenticatorParams fromPortalConfigResponse(const PortalConfigResponse &portalConfig);
const QString &username() const;
void setUsername(const QString &newUsername);
const QString &password() const;
void setPassword(const QString &newPassword);
const QString &userAuthCookie() const;
void setUserAuthCookie(const QString &newUserAuthCookie);
const QString &clientos() const;
void setClientos(const QString &newClientos);
private:
QString m_username;
QString m_password;
QString m_userAuthCookie;
QString m_clientos;
};
#endif // GATEWAYAUTHENTICATORPARAMS_H

View File

@@ -4,6 +4,7 @@
#include "portalauthenticator.h"
#include "gatewayauthenticator.h"
#include "settingsdialog.h"
#include "gatewayauthenticatorparams.h"
#include <plog/Log.h>
#include <QIcon>
@@ -30,6 +31,7 @@ GPClient::GPClient(QWidget *parent)
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);
// Initiallize the context menu of system tray.
@@ -66,12 +68,14 @@ void GPClient::setupSettings()
void GPClient::onSettingsButtonClicked()
{
settingsDialog->setExtraArgs(settings::get("extraArgs", "").toString());
settingsDialog->setClientos(settings::get("clientos", "").toString());
settingsDialog->show();
}
void GPClient::onSettingsAccepted()
{
settings::save("extraArgs", settingsDialog->extraArgs());
settings::save("clientos", settingsDialog->clientos());
}
void GPClient::on_connectButton_clicked()
@@ -274,7 +278,7 @@ void GPClient::doConnect()
// Login to the portal interface to get the portal config and preferred gateway
void GPClient::portalLogin()
{
PortalAuthenticator *portalAuth = new PortalAuthenticator(portal());
PortalAuthenticator *portalAuth = new PortalAuthenticator(portal(), settings::get("clientos", "").toString());
connect(portalAuth, &PortalAuthenticator::success, this, &GPClient::onPortalSuccess);
// Prelogin failed on the portal interface, try to treat the portal as a gateway interface
@@ -351,7 +355,10 @@ void GPClient::gatewayLogin()
{
PLOGI << "Performing gateway login...";
GatewayAuthenticator *gatewayAuth = new GatewayAuthenticator(currentGateway().address(), portalConfig);
GatewayAuthenticatorParams params = GatewayAuthenticatorParams::fromPortalConfigResponse(portalConfig);
params.setClientos(settings::get("clientos", "").toString());
GatewayAuthenticator *gatewayAuth = new GatewayAuthenticator(currentGateway().address(), params);
connect(gatewayAuth, &GatewayAuthenticator::success, this, &GPClient::onGatewaySuccess);
connect(gatewayAuth, &GatewayAuthenticator::fail, this, &GPClient::onGatewayFail);
@@ -471,6 +478,12 @@ void GPClient::onVPNDisconnected()
}
}
void GPClient::onVPNError(QString errorMessage)
{
updateConnectionStatus(VpnStatus::disconnected);
openMessageBox("Failed to connect", errorMessage);
}
void GPClient::onVPNLogAvailable(QString log)
{
PLOGI << log;

View File

@@ -45,6 +45,7 @@ private slots:
void onVPNConnected();
void onVPNDisconnected();
void onVPNError(QString errorMessage);
void onVPNLogAvailable(QString log);
private:

View File

@@ -116,7 +116,13 @@ void gpclient::helper::settings::save(const QString &key, const QVariant &value)
_settings->setValue(key, value);
}
void gpclient::helper::settings::clear()
{
_settings->clear();
QStringList keys = _settings->allKeys();
for (const auto &key : qAsConst(keys)) {
if (!reservedKeys.contains(key)) {
_settings->remove(key);
}
}
}

View File

@@ -31,6 +31,7 @@ namespace gpclient {
namespace settings {
extern QSettings *_settings;
static const QStringList reservedKeys {"extraArgs", "clientos"};
QVariant get(const QString &key, const QVariant &defaultValue = QVariant());
void save(const QString &key, const QVariant &value);

View File

@@ -15,7 +15,6 @@ LoginParams::LoginParams()
params.addQueryItem("direct", "yes");
params.addQueryItem("clientVer", "4100");
params.addQueryItem("os-version", QUrl::toPercentEncoding(QSysInfo::prettyProductName()));
params.addQueryItem("clientos", "Linux");
params.addQueryItem("portal-userauthcookie", "");
params.addQueryItem("portal-prelogonuserauthcookie", "");
params.addQueryItem("prelogin-cookie", "");
@@ -56,6 +55,11 @@ void LoginParams::setPreloginCookie(const QString cookie)
updateQueryItem("prelogin-cookie", cookie);
}
void LoginParams::setClientos(const QString clientos)
{
updateQueryItem("clientos", clientos);
}
QByteArray LoginParams::toUtf8() const
{
return params.toString().toUtf8();

View File

@@ -15,6 +15,7 @@ public:
void setUserAuthCookie(const QString cookie);
void setPrelogonAuthCookie(const QString cookie);
void setPreloginCookie(const QString cookie);
void setClientos(const QString clientos);
QByteArray toUtf8() const;

View File

@@ -6,7 +6,7 @@
#include <plog/Log.h>
#include <plog/Appenders/ColorConsoleAppender.h>
static const QString version = "v1.3.0";
static const QString version = "v1.3.1";
int main(int argc, char *argv[])
{

View File

@@ -12,11 +12,14 @@
using namespace gpclient::helper;
PortalAuthenticator::PortalAuthenticator(const QString& portal) : QObject()
PortalAuthenticator::PortalAuthenticator(const QString& portal, const QString& clientos) : QObject()
, portal(portal)
, preloginUrl("https://" + portal + "/global-protect/prelogin.esp?tmp=tmp&kerberos-support=yes&ipv6-support=yes&clientVer=4100&clientos=Linux")
, preloginUrl("https://" + portal + "/global-protect/prelogin.esp?tmp=tmp&kerberos-support=yes&ipv6-support=yes&clientVer=4100")
, configUrl("https://" + portal + "/global-protect/getconfig.esp")
{
if (!clientos.isEmpty()) {
preloginUrl = preloginUrl + "&clientos=" + clientos;
}
}
PortalAuthenticator::~PortalAuthenticator()

View File

@@ -12,7 +12,7 @@ class PortalAuthenticator : public QObject
{
Q_OBJECT
public:
explicit PortalAuthenticator(const QString& portal);
explicit PortalAuthenticator(const QString& portal, const QString& clientos);
~PortalAuthenticator();
void authenticate();

View File

@@ -46,17 +46,17 @@ PortalConfigResponse PortalConfigResponse::parse(const QByteArray xml)
const QByteArray PortalConfigResponse::rawResponse() const
{
return _rawResponse;
return m_rawResponse;
}
QString PortalConfigResponse::username() const
const QString &PortalConfigResponse::username() const
{
return _username;
return m_username;
}
QString PortalConfigResponse::password() const
{
return _password;
return m_password;
}
QList<GPGateway> PortalConfigResponse::parseGateways(QXmlStreamReader &xmlReader)
@@ -134,45 +134,45 @@ QString PortalConfigResponse::parseGatewayName(QXmlStreamReader &xmlReader)
QString PortalConfigResponse::userAuthCookie() const
{
return _userAuthCookie;
return m_userAuthCookie;
}
QString PortalConfigResponse::prelogonUserAuthCookie() const
{
return _prelogonAuthCookie;
return m_prelogonAuthCookie;
}
QList<GPGateway> PortalConfigResponse::allGateways() const
{
return _gateways;
return m_gateways;
}
void PortalConfigResponse::setAllGateways(QList<GPGateway> gateways)
{
_gateways = gateways;
m_gateways = gateways;
}
void PortalConfigResponse::setRawResponse(const QByteArray response)
{
_rawResponse = response;
m_rawResponse = response;
}
void PortalConfigResponse::setUsername(const QString username)
{
_username = username;
m_username = username;
}
void PortalConfigResponse::setPassword(const QString password)
{
_password = password;
m_password = password;
}
void PortalConfigResponse::setUserAuthCookie(const QString cookie)
{
_userAuthCookie = cookie;
m_userAuthCookie = cookie;
}
void PortalConfigResponse::setPrelogonUserAuthCookie(const QString cookie)
{
_prelogonAuthCookie = cookie;
m_prelogonAuthCookie = cookie;
}

View File

@@ -16,7 +16,7 @@ public:
static PortalConfigResponse parse(const QByteArray xml);
const QByteArray rawResponse() const;
QString username() const;
const QString &username() const;
QString password() const;
QString userAuthCookie() const;
QString prelogonUserAuthCookie() const;
@@ -31,13 +31,13 @@ private:
static QString xmlPrelogonUserAuthCookie;
static QString xmlGateways;
QByteArray _rawResponse;
QString _username;
QString _password;
QString _userAuthCookie;
QString _prelogonAuthCookie;
QByteArray m_rawResponse;
QString m_username;
QString m_password;
QString m_userAuthCookie;
QString m_prelogonAuthCookie;
QList<GPGateway> _gateways;
QList<GPGateway> m_gateways;
void setRawResponse(const QByteArray response);
void setUserAuthCookie(const QString cookie);

View File

@@ -6,8 +6,6 @@ SettingsDialog::SettingsDialog(QWidget *parent) :
ui(new Ui::SettingsDialog)
{
ui->setupUi(this);
ui->extraArgsInput->setPlaceholderText("e.g. --name=value");
}
SettingsDialog::~SettingsDialog()
@@ -15,12 +13,22 @@ SettingsDialog::~SettingsDialog()
delete ui;
}
void SettingsDialog::setExtraArgs(QString args)
void SettingsDialog::setExtraArgs(QString extraArgs)
{
ui->extraArgsInput->setPlainText(args);
ui->extraArgsInput->setPlainText(extraArgs);
}
QString SettingsDialog::extraArgs()
{
return ui->extraArgsInput->toPlainText().trimmed();
}
void SettingsDialog::setClientos(QString clientos)
{
ui->clientosInput->setText(clientos);
}
QString SettingsDialog::clientos()
{
return ui->clientosInput->text();
}

View File

@@ -15,9 +15,12 @@ public:
explicit SettingsDialog(QWidget *parent = nullptr);
~SettingsDialog();
void setExtraArgs(QString);
void setExtraArgs(QString extraArgs);
QString extraArgs();
void setClientos(QString clientos);
QString clientos();
private:
Ui::SettingsDialog *ui;
};

View File

@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>470</width>
<height>183</height>
<width>488</width>
<height>177</height>
</rect>
</property>
<property name="sizePolicy">
@@ -23,18 +23,36 @@
<iconset resource="resources.qrc">
<normaloff>:/images/connected.png</normaloff>:/images/connected.png</iconset>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QFormLayout" name="formLayout_3">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Custom Parameters:</string>
</property>
</widget>
</item>
<item>
<widget class="QPlainTextEdit" name="extraArgsInput"/>
<item row="0" column="1">
<widget class="QPlainTextEdit" name="extraArgsInput">
<property name="placeholderText">
<string extracomment="Tokens with spaces can be surrounded by double quotes">e.g. --name=value --script=&quot;vpn-slice xxx&quot;</string>
</property>
</widget>
</item>
<item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Value of &quot;clientos&quot;:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="clientosInput">
<property name="placeholderText">
<string>e.g., Windows</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>

View File

@@ -39,6 +39,47 @@ QString GPService::findBinary()
return nullptr;
}
/* Port from https://github.com/qt/qtbase/blob/11d1dcc6e263c5059f34b44d531c9ccdf7c0b1d6/src/corelib/io/qprocess.cpp#L2115 */
QStringList GPService::splitCommand(QStringView command)
{
QStringList args;
QString tmp;
int quoteCount = 0;
bool inQuote = false;
// handle quoting. tokens can be surrounded by double quotes
// "hello world". three consecutive double quotes represent
// the quote character itself.
for (int i = 0; i < command.size(); ++i) {
if (command.at(i) == QLatin1Char('"')) {
++quoteCount;
if (quoteCount == 3) {
// third consecutive quote
quoteCount = 0;
tmp += command.at(i);
}
continue;
}
if (quoteCount) {
if (quoteCount == 1)
inQuote = !inQuote;
quoteCount = 0;
}
if (!inQuote && command.at(i).isSpace()) {
if (!tmp.isEmpty()) {
args += tmp;
tmp.clear();
}
} else {
tmp += command.at(i);
}
}
if (!tmp.isEmpty())
args += tmp;
return args;
}
void GPService::quit()
{
if (openconnect->state() == QProcess::NotRunning) {
@@ -58,14 +99,15 @@ void GPService::connect(QString server, QString username, QString passwd, QStrin
QString bin = findBinary();
if (bin == nullptr) {
log("Could not found openconnect binary, make sure openconnect is installed, exiting.");
log("Could not find openconnect binary, make sure openconnect is installed, exiting.");
emit error("The OpenConect CLI was not found, make sure it has been installed!");
return;
}
QStringList args;
args << QCoreApplication::arguments().mid(1)
<< "--protocol=gp"
<< QProcess::splitCommand(extraArgs)
<< splitCommand(extraArgs)
<< "-u" << username
<< "-C" << passwd
<< server;

View File

@@ -31,6 +31,7 @@ public:
signals:
void connected();
void disconnected();
void error(QString errorMessage);
void logAvailable(QString log);
public slots:
@@ -53,6 +54,7 @@ private:
void log(QString msg);
static QString findBinary();
static QStringList splitCommand(QStringView command);
};
#endif // GLOBALPROTECTSERVICE_H

View File

@@ -8,6 +8,9 @@
<signal name="logAvailable">
<arg name="log" type="s" />
</signal>
<signal name="error">
<arg name="errorMessage" type="s" />
</signal>
<method name="connect">
<arg name="server" type="s" direction="in"/>
<arg name="username" type="s" direction="in"/>

View File

@@ -12,13 +12,32 @@ A GlobalProtect VPN client (GUI) for Linux based on Openconnect and built with Q
- Supports automatically selecting the preferred gateway from the multiple gateways.
- Supports switching gateway from the system tray menu manually.
## Future plan
- [ ] Improve the release process
- [ ] Process bugs and feature requests
- [ ] Support for bypassing the `gpclient` parameters
- [ ] Support the CLI mode
## Passing the Custom Parameters to `OpenConnect` CLI
Custom parameters can be appended to the `OpenConnect` CLI with the following settings.
> Tokens with spaces can be surrounded by double quotes; three consecutive double quotes represent the quote character itself.
<p align="center">
<img src="https://user-images.githubusercontent.com/3297602/129464304-94eb8a2b-1c4a-47e1-b931-4422fff6eb81.png" />
<img src="https://user-images.githubusercontent.com/3297602/130319209-744be02b-d657-4f49-a76d-d2c81b5c46d5.png" />
<p>
## Display the system tray icon on Gnome 40
Install the [AppIndicator and KStatusNotifierItem Support](https://extensions.gnome.org/extension/615/appindicator-support/) extension and you will see the system try icon (Restart the system after the installation).
<p align="center">
<img src="https://user-images.githubusercontent.com/3297602/130831022-b93492fd-46dd-4a8e-94a4-13b5747120b7.png" />
<p>
## Prerequisites
- Openconnect v8.x
@@ -59,7 +78,7 @@ sudo zypper install libqt5-qtbase-devel libqt5-qtwebsockets-devel libqt5-qtweben
Install the Qt dependencies:
```sh
sudo dnf install qt5-qtbase-devel qt5-qttools-devel qt5-qtwebengine qt5-qtwebsockets-devel qt5-qtwebengine-devel
sudo dnf install qt5-qtbase-devel qt5-qtwebengine-devel qt5-qtwebsockets-devel
```
## Install

5
packaging/rpm/README.md Normal file
View File

@@ -0,0 +1,5 @@
## Command
```sh
docker run --rm -it -v ${PWD}:/rpm --workdir=/rpm --entrypoint ./entrypoint.sh centos:8
```

21
packaging/rpm/entrypoint.sh Executable file
View File

@@ -0,0 +1,21 @@
#!/bin/bash -e
# Install the build tools
dnf install -y epel-release
rpm --import http://download.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-8
dnf install -y make rpm-build rpm-devel rpmlint rpmdevtools
# Install the build dependencies
dnf install -y qt5-qtbase-devel qt5-qtwebengine-devel qt5-qtwebsockets-devel
# Prepare the RPM build environment
rpmdev-setuptree
cp *.spec $HOME/rpmbuild/SPECS/
cp *.tar.gz $HOME/rpmbuild/SOURCES/
# Build
rpmbuild -ba $HOME/rpmbuild/SPECS/globalprotect-openconnect.spec
# Copy the package to the current directory
cp $HOME/rpmbuild/RPMS/x86_64/globalprotect-openconnect-*.rpm .
cp $HOME/rpmbuild/SRPMS/globalprotect-openconnect-*.src.rpm .

View File

@@ -0,0 +1,39 @@
Name: globalprotect-openconnect
Version: 1.3.0+SNAPSHOT20210829120923
Release: 1
Summary: A GlobalProtect VPN client
License: GPLv3
URL: https://github.com/yuezk/GlobalProtect-openconnect
Source0: %{url}/releases/download/latest/globalprotect-openconnect_%{version}.full.tar.gz
BuildRequires: qt5-qtbase-devel qt5-qtwebengine-devel qt5-qtwebsockets-devel
Requires: qt5-qtbase >= 5.12 qt5-qtwebengine >= 5.12 qt5-qtwebsockets >= 5.12 openconnect >= 8.0
%global debug_package %{nil}
%description
A GlobalProtect VPN client (GUI) for Linux based on OpenConnect and built with Qt5, supports SAML auth mode.
%prep
%autosetup
%build
qmake-qt5 CONFIG+=release
%make_build
%install
INSTALL_ROOT=${RPM_BUILD_ROOT} %make_install
%files
/etc/systemd/system/gpservice.service
/usr/bin/gpclient
/usr/bin/gpservice
/usr/share/applications/com.yuezk.qt.gpclient.desktop
/usr/share/dbus-1/system-services/com.yuezk.qt.GPService.service
/usr/share/dbus-1/system.d/com.yuezk.qt.GPService.conf
/usr/share/pixmaps/com.yuezk.qt.GPClient.svg