From 0d4485d75497b571e68d903505ef47697d8e34f0 Mon Sep 17 00:00:00 2001 From: Kevin Yue Date: Fri, 10 Sep 2021 22:49:54 +0800 Subject: [PATCH 1/4] Update README.md --- README.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6048d11..2b521f5 100644 --- a/README.md +++ b/README.md @@ -51,9 +51,15 @@ Install the [AppIndicator and KStatusNotifierItem Support](https://extensions.gn openconnect --version ``` - For Ubuntu 18.04 you might need to [build the latest openconnect from source code](https://gist.github.com/yuezk/ab9a4b87a9fa0182bdb2df41fab5f613). + For Ubuntu 18.04, using this [dwmw2/openconnect](https://launchpad.net/~dwmw2/+archive/ubuntu/openconnect) PPA. + + ```sh + sudo add-apt-repository ppa:dwmw2/openconnect + sudo apt-get update + sudo apt install openconnect + ``` -2. Install the Qt dependencies +1. Install the Qt dependencies For Ubuntu 20, this should work. From 5c97b2df7a0c569a95cc9f95435647e5e92ce6a9 Mon Sep 17 00:00:00 2001 From: Kevin Yue Date: Tue, 14 Sep 2021 00:32:05 +0800 Subject: [PATCH 2/4] QStringView -> QString --- GPService/gpservice.cpp | 2 +- GPService/gpservice.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/GPService/gpservice.cpp b/GPService/gpservice.cpp index 04d018f..6e3c484 100644 --- a/GPService/gpservice.cpp +++ b/GPService/gpservice.cpp @@ -40,7 +40,7 @@ QString GPService::findBinary() } /* Port from https://github.com/qt/qtbase/blob/11d1dcc6e263c5059f34b44d531c9ccdf7c0b1d6/src/corelib/io/qprocess.cpp#L2115 */ -QStringList GPService::splitCommand(QStringView command) +QStringList GPService::splitCommand(QString command) { QStringList args; QString tmp; diff --git a/GPService/gpservice.h b/GPService/gpservice.h index 63c4e5a..7f547a3 100644 --- a/GPService/gpservice.h +++ b/GPService/gpservice.h @@ -54,7 +54,7 @@ private: void log(QString msg); static QString findBinary(); - static QStringList splitCommand(QStringView command); + static QStringList splitCommand(QString command); }; #endif // GLOBALPROTECTSERVICE_H From 8a65099ca7479102db6aa0217e35e42fa81afab0 Mon Sep 17 00:00:00 2001 From: Kevin Yue Date: Sun, 19 Sep 2021 14:32:12 +0800 Subject: [PATCH 3/4] Migrate to cmake and refine the code structure (#92) * migrate to cmake * move the 3rd party libs * organize 3rdparty * update the 3rd party version * refine the CMakeLists.txt * update install command * update install command * update install command * update install command * update dependency * update the dependency * update the dependency * remove CPM.cmake * remove QtCreator project file * update cmake file * improve cmake file * add cmakew * use wget * remove echo * update the doc * remove the screenshot * update the doc * update the install steps * check the openconnect version * update the doc * update install scripts * fix install scripts * improve message * improve message * improve install scripts * improve the version check * improve the version check * improve install script * add version * organize includes * add version bump * update CI * update CI * add the release flag * update message --- .github/workflows/main.yml | 29 +- .gitignore | 3 + .gitmodules | 4 +- .vscode/settings.json | 23 ++ 3rdparty/SingleApplication | 1 + 3rdparty/plog | 1 + CMakeLists.txt | 26 ++ GPClient/CMakeLists.txt | 78 +++++ GPClient/GPClient.pro | 83 ----- GPClient/cdpcommand.cpp | 8 +- GPClient/cdpcommand.h | 2 +- GPClient/cdpcommandmanager.cpp | 5 +- GPClient/cdpcommandmanager.h | 9 +- GPClient/enhancedwebview.cpp | 6 +- GPClient/enhancedwebview.h | 3 +- GPClient/gatewayauthenticator.cpp | 6 +- GPClient/gatewayauthenticator.h | 3 +- GPClient/gatewayauthenticatorparams.h | 3 +- GPClient/gpclient.cpp | 6 +- GPClient/gpclient.h | 12 +- GPClient/gpgateway.cpp | 8 +- GPClient/gpgateway.h | 6 +- GPClient/gphelper.cpp | 19 +- GPClient/gphelper.h | 14 +- GPClient/loginparams.cpp | 4 +- GPClient/loginparams.h | 2 +- GPClient/main.cpp | 16 +- GPClient/normalloginwindow.cpp | 4 +- GPClient/normalloginwindow.h | 2 +- GPClient/portalauthenticator.cpp | 6 +- GPClient/portalauthenticator.h | 3 +- GPClient/portalconfigresponse.cpp | 6 +- GPClient/portalconfigresponse.h | 8 +- GPClient/preloginresponse.cpp | 8 +- GPClient/preloginresponse.h | 4 +- GPClient/samlloginwindow.cpp | 10 +- GPClient/samlloginwindow.h | 8 +- GPClient/settingsdialog.h | 2 +- GPService/CMakeLists.txt | 57 ++++ GPService/GPService.pro | 52 --- GPService/gpservice.cpp | 54 ++- GPService/gpservice.h | 8 +- GPService/gpservice.xml | 26 -- GPService/main.cpp | 3 +- GlobalProtect-openconnect.pro | 5 - PKGBUILD.template | 14 +- README.md | 107 +++--- VERSION | 1 + cmake/Add3rdParty.cmake | 27 ++ cmakew | 102 ++++++ plog | 1 - screenshot.png | Bin 24189 -> 0 bytes scripts/bump-version.sh | 452 ++++++++++++++++++++++++++ scripts/install-fedora.sh | 9 + scripts/install-opensuse.sh | 9 + scripts/install-ubuntu.sh | 11 + scripts/install.sh | 10 + singleapplication | 1 - version.h.in | 1 + 59 files changed, 1034 insertions(+), 357 deletions(-) create mode 100644 .vscode/settings.json create mode 160000 3rdparty/SingleApplication create mode 160000 3rdparty/plog create mode 100644 CMakeLists.txt create mode 100644 GPClient/CMakeLists.txt delete mode 100644 GPClient/GPClient.pro create mode 100644 GPService/CMakeLists.txt delete mode 100644 GPService/GPService.pro delete mode 100644 GPService/gpservice.xml delete mode 100644 GlobalProtect-openconnect.pro create mode 100644 VERSION create mode 100644 cmake/Add3rdParty.cmake create mode 100755 cmakew delete mode 160000 plog delete mode 100644 screenshot.png create mode 100755 scripts/bump-version.sh create mode 100755 scripts/install-fedora.sh create mode 100755 scripts/install-opensuse.sh create mode 100755 scripts/install-ubuntu.sh create mode 100755 scripts/install.sh delete mode 160000 singleapplication create mode 100644 version.h.in diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 14e13b0..2d720e6 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -2,29 +2,34 @@ name: Build on: push: - branches: [ master ] + branches: + - master + - dev + paths-ignore: + - LICENSE + - "*.md" + - .vscode pull_request: - branches: [ master ] + branches: + - master + - dev + paths-ignore: + - LICENSE + - "*.md" + - .vscode workflow_dispatch: # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: build: - runs-on: ubuntu-latest + runs-on: ubuntu-18.04 steps: - - name: Install Qt - uses: jurplel/install-qt-action@v2 - with: - version: 5.12.11 - modules: 'qtwebengine qtwebsockets' - # Checkout repository and submodules - uses: actions/checkout@v2 with: submodules: recursive - - name: Build + - name: Build & Install run: | - qmake CONFIG+=release - make + ./scripts/install-ubuntu.sh \ No newline at end of file diff --git a/.gitignore b/.gitignore index 6c77b7e..6257a23 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,9 @@ gpservice *.gz .DS_Store build-debian +build + +.cmake # Auto generated DBus files *_adaptor.cpp diff --git a/.gitmodules b/.gitmodules index a95cc4c..45a9506 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,7 +1,7 @@ [submodule "singleapplication"] - path = singleapplication + path = 3rdparty/SingleApplication url = https://github.com/itay-grudev/SingleApplication.git [submodule "plog"] - path = plog + path = 3rdparty/plog url = https://github.com/SergiusTheBest/plog.git diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..fab9481 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,23 @@ +{ + "files.associations": { + "qregularexpression": "cpp", + "qfileinfo": "cpp", + "qregularexpressionmatch": "cpp", + "qdatetime": "cpp", + "qprocess": "cpp", + "qobject": "cpp", + "qstandardpaths": "cpp", + "qmainwindow": "cpp", + "qsystemtrayicon": "cpp", + "qpushbutton": "cpp", + "qmenu": "cpp", + "qjsondocument": "cpp", + "qnetworkaccessmanager": "cpp", + "qwebengineview": "cpp", + "qprocessenvironment": "cpp", + "qnetworkreply": "cpp", + "qicon": "cpp", + "qsslsocket": "cpp", + "qapplication": "cpp" + } +} \ No newline at end of file diff --git a/3rdparty/SingleApplication b/3rdparty/SingleApplication new file mode 160000 index 0000000..bdbb09b --- /dev/null +++ b/3rdparty/SingleApplication @@ -0,0 +1 @@ +Subproject commit bdbb09b5f21ebea4cd7dfb43b29114a94e04a3a1 diff --git a/3rdparty/plog b/3rdparty/plog new file mode 160000 index 0000000..f4c22b0 --- /dev/null +++ b/3rdparty/plog @@ -0,0 +1 @@ +Subproject commit f4c22b03d5d3aa753cca8e716636ac4eb29b0917 diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..b4f6095 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,26 @@ +cmake_minimum_required(VERSION 3.10.0) + +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_AUTOUIC ON) + +file(READ "VERSION" ver) +project(GlobalProtect-openconnect VERSION ${ver} LANGUAGES CXX) + +configure_file(version.h.in version.h) + +find_package(Qt5 REQUIRED COMPONENTS + Core + Widgets + Network + WebSockets + WebEngine + WebEngineWidgets + DBus +) + +add_subdirectory(GPService) +add_subdirectory(GPClient) diff --git a/GPClient/CMakeLists.txt b/GPClient/CMakeLists.txt new file mode 100644 index 0000000..e149e82 --- /dev/null +++ b/GPClient/CMakeLists.txt @@ -0,0 +1,78 @@ +include("${CMAKE_SOURCE_DIR}/cmake/Add3rdParty.cmake") + +project(GPClient) + +set(gpclient_GENERATED_SOURCES) + +qt5_add_dbus_interface(gpclient_GENERATED_SOURCES ${CMAKE_BINARY_DIR}/com.yuezk.qt.GPService.xml gpserviceinterface) + +add_executable(gpclient + cdpcommand.cpp + cdpcommandmanager.cpp + enhancedwebview.cpp + gatewayauthenticator.cpp + gatewayauthenticatorparams.cpp + gpgateway.cpp + gphelper.cpp + loginparams.cpp + main.cpp + normalloginwindow.cpp + portalauthenticator.cpp + portalconfigresponse.cpp + preloginresponse.cpp + samlloginwindow.cpp + gpclient.cpp + settingsdialog.cpp + gpclient.ui + normalloginwindow.ui + settingsdialog.ui + resources.qrc + ${gpclient_GENERATED_SOURCES} +) + +add_3rdparty( + SingleApplication + GIT_REPOSITORY https://github.com/itay-grudev/SingleApplication.git + GIT_TAG v3.3.0 + CMAKE_ARGS -DQAPPLICATION_CLASS=QApplication +) + +add_3rdparty( + plog + GIT_REPOSITORY https://github.com/SergiusTheBest/plog.git + GIT_TAG 1.1.5 + CMAKE_ARGS -DPLOG_BUILD_SAMPLES=OFF +) + +ExternalProject_Get_Property(SingleApplication-${PROJECT_NAME} SOURCE_DIR BINARY_DIR) +set(SingleApplication_INCLUDE_DIR ${SOURCE_DIR}) +set(SingleApplication_LIBRARY ${BINARY_DIR}/libSingleApplication.a) + +ExternalProject_Get_Property(plog-${PROJECT_NAME} SOURCE_DIR) +set(plog_INCLUDE_DIR "${SOURCE_DIR}/include") + +add_dependencies(gpclient SingleApplication-${PROJECT_NAME} plog-${PROJECT_NAME}) + +target_include_directories(gpclient PRIVATE + ${CMAKE_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} + ${SingleApplication_INCLUDE_DIR} + ${plog_INCLUDE_DIR} +) + +target_link_libraries(gpclient + ${SingleApplication_LIBRARY} + Qt5::Widgets + Qt5::Network + Qt5::WebSockets + Qt5::WebEngine + Qt5::WebEngineWidgets + Qt5::DBus +) + +target_compile_definitions(gpclient PUBLIC QAPPLICATION_CLASS=QApplication) + +install(TARGETS gpclient DESTINATION "/usr/bin") +install(FILES com.yuezk.qt.gpclient.desktop DESTINATION "/usr/share/applications") +install(FILES com.yuezk.qt.GPClient.svg DESTINATION "/usr/share/pixmaps") diff --git a/GPClient/GPClient.pro b/GPClient/GPClient.pro deleted file mode 100644 index ec6f90b..0000000 --- a/GPClient/GPClient.pro +++ /dev/null @@ -1,83 +0,0 @@ -TARGET = gpclient - -QT += core gui network websockets dbus webenginewidgets - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -CONFIG += c++11 - -include(../singleapplication/singleapplication.pri) -DEFINES += QAPPLICATION_CLASS=QApplication - -# The following define makes your compiler emit warnings if you use -# any Qt feature that has been marked deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -INCLUDEPATH += ../plog/include - -# You can also make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 -SOURCES += \ - cdpcommand.cpp \ - cdpcommandmanager.cpp \ - enhancedwebview.cpp \ - gatewayauthenticator.cpp \ - gatewayauthenticatorparams.cpp \ - gpgateway.cpp \ - gphelper.cpp \ - loginparams.cpp \ - main.cpp \ - normalloginwindow.cpp \ - portalauthenticator.cpp \ - portalconfigresponse.cpp \ - preloginresponse.cpp \ - samlloginwindow.cpp \ - gpclient.cpp \ - settingsdialog.cpp - -HEADERS += \ - cdpcommand.h \ - cdpcommandmanager.h \ - enhancedwebview.h \ - gatewayauthenticator.h \ - gatewayauthenticatorparams.h \ - gpgateway.h \ - gphelper.h \ - loginparams.h \ - normalloginwindow.h \ - portalauthenticator.h \ - portalconfigresponse.h \ - preloginresponse.h \ - samlloginwindow.h \ - gpclient.h \ - settingsdialog.h - -FORMS += \ - gpclient.ui \ - normalloginwindow.ui \ - settingsdialog.ui - -DBUS_INTERFACES += ../GPService/gpservice.xml - -# Default rules for deployment. -target.path = /usr/bin -INSTALLS += target - -DISTFILES += \ - com.yuezk.qt.GPClient.svg \ - com.yuezk.qt.gpclient.desktop - -desktop_entry.path = /usr/share/applications/ -desktop_entry.files = com.yuezk.qt.gpclient.desktop - -desktop_icon.path = /usr/share/pixmaps/ -desktop_icon.files = com.yuezk.qt.GPClient.svg - -INSTALLS += desktop_entry desktop_icon - -RESOURCES += \ - resources.qrc diff --git a/GPClient/cdpcommand.cpp b/GPClient/cdpcommand.cpp index 10d3f48..0722aac 100644 --- a/GPClient/cdpcommand.cpp +++ b/GPClient/cdpcommand.cpp @@ -1,8 +1,8 @@ -#include "cdpcommand.h" +#include +#include +#include -#include -#include -#include +#include "cdpcommand.h" CDPCommand::CDPCommand(QObject *parent) : QObject(parent) { diff --git a/GPClient/cdpcommand.h b/GPClient/cdpcommand.h index 75cbdbe..8f37b7b 100644 --- a/GPClient/cdpcommand.h +++ b/GPClient/cdpcommand.h @@ -1,7 +1,7 @@ #ifndef CDPCOMMAND_H #define CDPCOMMAND_H -#include +#include class CDPCommand : public QObject { diff --git a/GPClient/cdpcommandmanager.cpp b/GPClient/cdpcommandmanager.cpp index 9969dbd..e4e20f5 100644 --- a/GPClient/cdpcommandmanager.cpp +++ b/GPClient/cdpcommandmanager.cpp @@ -1,7 +1,8 @@ -#include "cdpcommandmanager.h" -#include +#include #include +#include "cdpcommandmanager.h" + CDPCommandManager::CDPCommandManager(QObject *parent) : QObject(parent) , networkManager(new QNetworkAccessManager) diff --git a/GPClient/cdpcommandmanager.h b/GPClient/cdpcommandmanager.h index 9aefedf..ef1238f 100644 --- a/GPClient/cdpcommandmanager.h +++ b/GPClient/cdpcommandmanager.h @@ -1,11 +1,12 @@ #ifndef CDPCOMMANDMANAGER_H #define CDPCOMMANDMANAGER_H +#include +#include +#include +#include + #include "cdpcommand.h" -#include -#include -#include -#include class CDPCommandManager : public QObject { diff --git a/GPClient/enhancedwebview.cpp b/GPClient/enhancedwebview.cpp index 292c6ff..8ac3ac1 100644 --- a/GPClient/enhancedwebview.cpp +++ b/GPClient/enhancedwebview.cpp @@ -1,9 +1,9 @@ +#include +#include + #include "enhancedwebview.h" #include "cdpcommandmanager.h" -#include -#include - EnhancedWebView::EnhancedWebView(QWidget *parent) : QWebEngineView(parent) , cdp(new CDPCommandManager) diff --git a/GPClient/enhancedwebview.h b/GPClient/enhancedwebview.h index 191364d..163768e 100644 --- a/GPClient/enhancedwebview.h +++ b/GPClient/enhancedwebview.h @@ -1,9 +1,10 @@ #ifndef ENHANCEDWEBVIEW_H #define ENHANCEDWEBVIEW_H -#include "cdpcommandmanager.h" #include +#include "cdpcommandmanager.h" + #define ENV_CDP_PORT "QTWEBENGINE_REMOTE_DEBUGGING" class EnhancedWebView : public QWebEngineView diff --git a/GPClient/gatewayauthenticator.cpp b/GPClient/gatewayauthenticator.cpp index 894a4ea..60e98de 100644 --- a/GPClient/gatewayauthenticator.cpp +++ b/GPClient/gatewayauthenticator.cpp @@ -1,11 +1,11 @@ +#include +#include + #include "gatewayauthenticator.h" #include "gphelper.h" #include "loginparams.h" #include "preloginresponse.h" -#include -#include - using namespace gpclient::helper; GatewayAuthenticator::GatewayAuthenticator(const QString& gateway, const GatewayAuthenticatorParams params) diff --git a/GPClient/gatewayauthenticator.h b/GPClient/gatewayauthenticator.h index 97f091c..c150a88 100644 --- a/GPClient/gatewayauthenticator.h +++ b/GPClient/gatewayauthenticator.h @@ -1,10 +1,11 @@ #ifndef GATEWAYAUTHENTICATOR_H #define GATEWAYAUTHENTICATOR_H +#include + #include "normalloginwindow.h" #include "loginparams.h" #include "gatewayauthenticatorparams.h" -#include class GatewayAuthenticator : public QObject { diff --git a/GPClient/gatewayauthenticatorparams.h b/GPClient/gatewayauthenticatorparams.h index cb25eae..72d9176 100644 --- a/GPClient/gatewayauthenticatorparams.h +++ b/GPClient/gatewayauthenticatorparams.h @@ -1,7 +1,8 @@ #ifndef GATEWAYAUTHENTICATORPARAMS_H #define GATEWAYAUTHENTICATORPARAMS_H -#include +#include + #include "portalconfigresponse.h" class GatewayAuthenticatorParams diff --git a/GPClient/gpclient.cpp b/GPClient/gpclient.cpp index 966f4bf..76cfd58 100644 --- a/GPClient/gpclient.cpp +++ b/GPClient/gpclient.cpp @@ -1,3 +1,6 @@ +#include +#include + #include "gpclient.h" #include "gphelper.h" #include "ui_gpclient.h" @@ -6,9 +9,6 @@ #include "settingsdialog.h" #include "gatewayauthenticatorparams.h" -#include -#include - using namespace gpclient::helper; GPClient::GPClient(QWidget *parent) diff --git a/GPClient/gpclient.h b/GPClient/gpclient.h index 45ca86d..690c026 100644 --- a/GPClient/gpclient.h +++ b/GPClient/gpclient.h @@ -1,15 +1,15 @@ #ifndef GPCLIENT_H #define GPCLIENT_H -#include "gpservice_interface.h" +#include +#include +#include +#include + +#include "gpserviceinterface.h" #include "portalconfigresponse.h" #include "settingsdialog.h" -#include -#include -#include -#include - QT_BEGIN_NAMESPACE namespace Ui { class GPClient; } QT_END_NAMESPACE diff --git a/GPClient/gpgateway.cpp b/GPClient/gpgateway.cpp index 5725925..7b587ed 100644 --- a/GPClient/gpgateway.cpp +++ b/GPClient/gpgateway.cpp @@ -1,8 +1,8 @@ -#include "gpgateway.h" +#include +#include +#include -#include -#include -#include +#include "gpgateway.h" GPGateway::GPGateway() { diff --git a/GPClient/gpgateway.h b/GPClient/gpgateway.h index 0bfb449..d879259 100644 --- a/GPClient/gpgateway.h +++ b/GPClient/gpgateway.h @@ -1,9 +1,9 @@ #ifndef GPGATEWAY_H #define GPGATEWAY_H -#include -#include -#include +#include +#include +#include class GPGateway { diff --git a/GPClient/gphelper.cpp b/GPClient/gphelper.cpp index 4b6b5bd..242992b 100644 --- a/GPClient/gphelper.cpp +++ b/GPClient/gphelper.cpp @@ -1,14 +1,15 @@ -#include "gphelper.h" -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include #include +#include "gphelper.h" + QNetworkAccessManager* gpclient::helper::networkManager = new QNetworkAccessManager; QNetworkReply* gpclient::helper::createRequest(QString url, QByteArray params) diff --git a/GPClient/gphelper.h b/GPClient/gphelper.h index 66aa63a..fb74899 100644 --- a/GPClient/gphelper.h +++ b/GPClient/gphelper.h @@ -1,16 +1,16 @@ #ifndef GPHELPER_H #define GPHELPER_H +#include +#include +#include +#include +#include +#include + #include "samlloginwindow.h" #include "gpgateway.h" -#include -#include -#include -#include -#include -#include - const QString UA = "PAN GlobalProtect"; diff --git a/GPClient/loginparams.cpp b/GPClient/loginparams.cpp index 54850c9..5b59fe3 100644 --- a/GPClient/loginparams.cpp +++ b/GPClient/loginparams.cpp @@ -1,6 +1,6 @@ -#include "loginparams.h" +#include -#include +#include "loginparams.h" LoginParams::LoginParams(const QString clientos) { diff --git a/GPClient/loginparams.h b/GPClient/loginparams.h index f83bca0..87d3d10 100644 --- a/GPClient/loginparams.h +++ b/GPClient/loginparams.h @@ -1,7 +1,7 @@ #ifndef LOGINPARAMS_H #define LOGINPARAMS_H -#include +#include class LoginParams { diff --git a/GPClient/main.cpp b/GPClient/main.cpp index 59fde3e..68c1a1f 100644 --- a/GPClient/main.cpp +++ b/GPClient/main.cpp @@ -1,12 +1,14 @@ -#include "singleapplication.h" -#include "gpclient.h" -#include "enhancedwebview.h" - -#include +#include +#include +#include +#include #include #include -static const QString version = "v1.3.3"; +#include "singleapplication.h" +#include "gpclient.h" +#include "enhancedwebview.h" +#include "version.h" int main(int argc, char *argv[]) { @@ -19,7 +21,7 @@ int main(int argc, char *argv[]) static plog::ColorConsoleAppender consoleAppender; plog::init(plog::debug, logFile.toUtf8()).addAppender(&consoleAppender); - PLOGI << "GlobalProtect started, version: " << version; + PLOGI << "GlobalProtect started, version: " << VERSION; QString port = QString::fromLocal8Bit(qgetenv(ENV_CDP_PORT)); diff --git a/GPClient/normalloginwindow.cpp b/GPClient/normalloginwindow.cpp index a712bee..1626a09 100644 --- a/GPClient/normalloginwindow.cpp +++ b/GPClient/normalloginwindow.cpp @@ -1,8 +1,8 @@ +#include + #include "normalloginwindow.h" #include "ui_normalloginwindow.h" -#include - NormalLoginWindow::NormalLoginWindow(QWidget *parent) : QDialog(parent), ui(new Ui::NormalLoginWindow) diff --git a/GPClient/normalloginwindow.h b/GPClient/normalloginwindow.h index d697aba..a2327bb 100644 --- a/GPClient/normalloginwindow.h +++ b/GPClient/normalloginwindow.h @@ -1,7 +1,7 @@ #ifndef PORTALAUTHWINDOW_H #define PORTALAUTHWINDOW_H -#include +#include namespace Ui { class NormalLoginWindow; diff --git a/GPClient/portalauthenticator.cpp b/GPClient/portalauthenticator.cpp index 7570a23..e0900ea 100644 --- a/GPClient/portalauthenticator.cpp +++ b/GPClient/portalauthenticator.cpp @@ -1,3 +1,6 @@ +#include +#include + #include "portalauthenticator.h" #include "gphelper.h" #include "normalloginwindow.h" @@ -7,9 +10,6 @@ #include "portalconfigresponse.h" #include "gpgateway.h" -#include -#include - using namespace gpclient::helper; PortalAuthenticator::PortalAuthenticator(const QString& portal, const QString& clientos) : QObject() diff --git a/GPClient/portalauthenticator.h b/GPClient/portalauthenticator.h index 0042bbd..4a39fc3 100644 --- a/GPClient/portalauthenticator.h +++ b/GPClient/portalauthenticator.h @@ -1,12 +1,13 @@ #ifndef PORTALAUTHENTICATOR_H #define PORTALAUTHENTICATOR_H +#include + #include "portalconfigresponse.h" #include "normalloginwindow.h" #include "samlloginwindow.h" #include "preloginresponse.h" -#include class PortalAuthenticator : public QObject { diff --git a/GPClient/portalconfigresponse.cpp b/GPClient/portalconfigresponse.cpp index 790056d..c5c578f 100644 --- a/GPClient/portalconfigresponse.cpp +++ b/GPClient/portalconfigresponse.cpp @@ -1,8 +1,8 @@ -#include "portalconfigresponse.h" - -#include +#include #include +#include "portalconfigresponse.h" + QString PortalConfigResponse::xmlUserAuthCookie = "portal-userauthcookie"; QString PortalConfigResponse::xmlPrelogonUserAuthCookie = "portal-prelogonuserauthcookie"; QString PortalConfigResponse::xmlGateways = "gateways"; diff --git a/GPClient/portalconfigresponse.h b/GPClient/portalconfigresponse.h index c79dae0..b6fe0d9 100644 --- a/GPClient/portalconfigresponse.h +++ b/GPClient/portalconfigresponse.h @@ -1,11 +1,11 @@ #ifndef PORTALCONFIGRESPONSE_H #define PORTALCONFIGRESPONSE_H -#include "gpgateway.h" +#include +#include +#include -#include -#include -#include +#include "gpgateway.h" class PortalConfigResponse { diff --git a/GPClient/preloginresponse.cpp b/GPClient/preloginresponse.cpp index d148b60..6fd6f40 100644 --- a/GPClient/preloginresponse.cpp +++ b/GPClient/preloginresponse.cpp @@ -1,9 +1,9 @@ -#include "preloginresponse.h" - -#include -#include +#include +#include #include +#include "preloginresponse.h" + QString PreloginResponse::xmlAuthMessage = "authentication-message"; QString PreloginResponse::xmlLabelUsername = "username-label"; QString PreloginResponse::xmlLabelPassword = "password-label"; diff --git a/GPClient/preloginresponse.h b/GPClient/preloginresponse.h index 1b8b09c..772a037 100644 --- a/GPClient/preloginresponse.h +++ b/GPClient/preloginresponse.h @@ -1,8 +1,8 @@ #ifndef PRELOGINRESPONSE_H #define PRELOGINRESPONSE_H -#include -#include +#include +#include class PreloginResponse { diff --git a/GPClient/samlloginwindow.cpp b/GPClient/samlloginwindow.cpp index 2729ca1..70d58b4 100644 --- a/GPClient/samlloginwindow.cpp +++ b/GPClient/samlloginwindow.cpp @@ -1,9 +1,9 @@ -#include "samlloginwindow.h" - -#include +#include +#include +#include #include -#include -#include + +#include "samlloginwindow.h" SAMLLoginWindow::SAMLLoginWindow(QWidget *parent) : QDialog(parent) diff --git a/GPClient/samlloginwindow.h b/GPClient/samlloginwindow.h index 09d8a2e..2d6bc79 100644 --- a/GPClient/samlloginwindow.h +++ b/GPClient/samlloginwindow.h @@ -1,11 +1,11 @@ #ifndef SAMLLOGINWINDOW_H #define SAMLLOGINWINDOW_H -#include "enhancedwebview.h" +#include +#include +#include -#include -#include -#include +#include "enhancedwebview.h" class SAMLLoginWindow : public QDialog { diff --git a/GPClient/settingsdialog.h b/GPClient/settingsdialog.h index 234db96..9e29e48 100644 --- a/GPClient/settingsdialog.h +++ b/GPClient/settingsdialog.h @@ -1,7 +1,7 @@ #ifndef SETTINGSDIALOG_H #define SETTINGSDIALOG_H -#include +#include namespace Ui { class SettingsDialog; diff --git a/GPService/CMakeLists.txt b/GPService/CMakeLists.txt new file mode 100644 index 0000000..c7205c3 --- /dev/null +++ b/GPService/CMakeLists.txt @@ -0,0 +1,57 @@ +include("${CMAKE_SOURCE_DIR}/cmake/Add3rdParty.cmake") + +project(GPService) + +set(gpservice_GENERATED_SOURCES) + +# generate the dbus xml definition +qt5_generate_dbus_interface(gpservice.h ${CMAKE_BINARY_DIR}/com.yuezk.qt.GPService.xml) + +# generate dbus adaptor +qt5_add_dbus_adaptor( + gpservice_GENERATED_SOURCES + ${CMAKE_BINARY_DIR}/com.yuezk.qt.GPService.xml + gpservice.h + GPService +) + +add_executable(gpservice + gpservice.cpp + main.cpp + sigwatch.cpp + ${gpservice_GENERATED_SOURCES} +) + +add_3rdparty( + SingleApplication + GIT_REPOSITORY https://github.com/itay-grudev/SingleApplication.git + GIT_TAG v3.3.0 + CMAKE_ARGS -DQAPPLICATION_CLASS=QCoreApplication +) + +ExternalProject_Get_Property(SingleApplication-${PROJECT_NAME} SOURCE_DIR BINARY_DIR) + +set(SingleApplication_INCLUDE_DIR ${SOURCE_DIR}) +set(SingleApplication_LIBRARY ${BINARY_DIR}/libSingleApplication.a) + +add_dependencies(gpservice SingleApplication-${PROJECT_NAME}) + +target_include_directories(gpservice PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} + ${SingleApplication_INCLUDE_DIR} +) + +target_link_libraries(gpservice + ${SingleApplication_LIBRARY} + Qt5::Core + Qt5::Network + Qt5::DBus +) + +target_compile_definitions(gpservice PUBLIC QAPPLICATION_CLASS=QCoreApplication) + +install(TARGETS gpservice DESTINATION "/usr/bin") +install(FILES "dbus/com.yuezk.qt.GPService.conf" DESTINATION "/usr/share/dbus-1/system.d" ) +install(FILES "dbus/com.yuezk.qt.GPService.service" DESTINATION "/usr/share/dbus-1/system-services") +install(FILES "systemd/gpservice.service" DESTINATION "/etc/systemd/system") diff --git a/GPService/GPService.pro b/GPService/GPService.pro deleted file mode 100644 index 4d22009..0000000 --- a/GPService/GPService.pro +++ /dev/null @@ -1,52 +0,0 @@ -TARGET = gpservice - -QT += dbus -QT -= gui - -CONFIG += c++11 console -CONFIG -= app_bundle - -include(../singleapplication/singleapplication.pri) -DEFINES += QAPPLICATION_CLASS=QCoreApplication - -# The following define makes your compiler emit warnings if you use -# any Qt feature that has been marked deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -HEADERS += \ - gpservice.h \ - sigwatch.h - -SOURCES += \ - gpservice.cpp \ - main.cpp \ - sigwatch.cpp - -DBUS_ADAPTORS += gpservice.xml - -# Default rules for deployment. -target.path = /usr/bin -INSTALLS += target - -DISTFILES += \ - dbus/com.yuezk.qt.GPService.conf \ - dbus/com.yuezk.qt.GPService.service \ - systemd/gpservice.service - -dbus_config.path = /usr/share/dbus-1/system.d/ -dbus_config.files = dbus/com.yuezk.qt.GPService.conf - -dbus_service.path = /usr/share/dbus-1/system-services/ -dbus_service.files = dbus/com.yuezk.qt.GPService.service - -systemd_service.path = /etc/systemd/system/ -systemd_service.files = systemd/gpservice.service - -INSTALLS += dbus_config dbus_service systemd_service diff --git a/GPService/gpservice.cpp b/GPService/gpservice.cpp index 6e3c484..7d0034b 100644 --- a/GPService/gpservice.cpp +++ b/GPService/gpservice.cpp @@ -1,10 +1,12 @@ -#include "gpservice.h" -#include "gpservice_adaptor.h" +#include +#include +#include +#include +#include +#include -#include -#include -#include -#include +#include "gpservice.h" +#include "gpserviceadaptor.h" GPService::GPService(QObject *parent) : QObject(parent) @@ -104,19 +106,49 @@ void GPService::connect(QString server, QString username, QString passwd, QStrin return; } + if (!isValidVersion(bin)) { + return; + } + QStringList args; args << QCoreApplication::arguments().mid(1) - << "--protocol=gp" - << splitCommand(extraArgs) - << "-u" << username - << "-C" << passwd - << server; + << "--protocol=gp" + << splitCommand(extraArgs) + << "-u" << username + << "-C" << passwd + << server; log("Start process with arugments: " + args.join(" ")); openconnect->start(bin, args); } +bool GPService::isValidVersion(QString &bin) { + QProcess p; + p.start(bin, QStringList("--version")); + p.waitForFinished(); + QString output = p.readAllStandardError() + p.readAllStandardOutput(); + + QRegularExpression re("v(\\d+).*?(\\s|\\n)"); + QRegularExpressionMatch match = re.match(output); + + if (match.hasMatch()) { + log("Output of `openconnect --version`: " + output); + + QString fullVersion = match.captured(0); + QString majorVersion = match.captured(1); + + if (majorVersion.toInt() < 8) { + emit error("The OpenConnect version must greater than v8.0.0, but got " + fullVersion); + return false; + } + } else { + log("Failed to parse the OpenConnect version from " + output); + } + + return true; +} + void GPService::disconnect() { if (openconnect->state() != QProcess::NotRunning) { diff --git a/GPService/gpservice.h b/GPService/gpservice.h index 7f547a3..a3b4856 100644 --- a/GPService/gpservice.h +++ b/GPService/gpservice.h @@ -1,8 +1,8 @@ #ifndef GLOBALPROTECTSERVICE_H #define GLOBALPROTECTSERVICE_H -#include -#include +#include +#include static const QString binaryPaths[] { "/usr/local/bin/openconnect", @@ -21,6 +21,8 @@ public: explicit GPService(QObject *parent = nullptr); ~GPService(); + void quit(); + enum VpnStatus { VpnNotConnected, VpnConnecting, @@ -38,7 +40,6 @@ public slots: void connect(QString server, QString username, QString passwd, QString extraArgs); void disconnect(); int status(); - void quit(); private slots: void onProcessStarted(); @@ -53,6 +54,7 @@ private: int vpnStatus = GPService::VpnNotConnected; void log(QString msg); + bool isValidVersion(QString &bin); static QString findBinary(); static QStringList splitCommand(QString command); }; diff --git a/GPService/gpservice.xml b/GPService/gpservice.xml deleted file mode 100644 index 9a9b8e8..0000000 --- a/GPService/gpservice.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/GPService/main.cpp b/GPService/main.cpp index 096fe10..06f8743 100644 --- a/GPService/main.cpp +++ b/GPService/main.cpp @@ -1,4 +1,5 @@ -#include +#include + #include "gpservice.h" #include "singleapplication.h" #include "sigwatch.h" diff --git a/GlobalProtect-openconnect.pro b/GlobalProtect-openconnect.pro deleted file mode 100644 index 00483f6..0000000 --- a/GlobalProtect-openconnect.pro +++ /dev/null @@ -1,5 +0,0 @@ -TEMPLATE = subdirs - -SUBDIRS += \ - GPClient \ - GPService diff --git a/PKGBUILD.template b/PKGBUILD.template index f34be1e..4456ab7 100644 --- a/PKGBUILD.template +++ b/PKGBUILD.template @@ -9,31 +9,25 @@ arch=(x86_64 aarch64) url="https://github.com/yuezk/${_gitname}" license=('GPL3') depends=('openconnect>=8.0.0' qt5-base qt5-webengine qt5-websockets) -makedepends=() +makedepends=(g++ make) source=( "${_gitname}-${pkgver}.tar.gz::${url}/archive/v${pkgver}.tar.gz" - "https://github.com/itay-grudev/SingleApplication/archive/v3.0.19.tar.gz" - "https://github.com/SergiusTheBest/plog/archive/1.1.5.tar.gz" ) sha256sums=( '{SOURCE_SHA}' - '9405fd259288b2a862e91e5135bccee936f0438e1b32c13603277132309d15e0' - '6c80b4701183d2415bec927e1f5ca9b1761b3b5c65d3e09fb29c743e016d5609' ); prepare() { - mv "$srcdir/SingleApplication-3.0.19" -T "$srcdir/${_gitname}-${pkgver}/singleapplication" - mv "$srcdir/plog-1.1.5" -T "$srcdir/${_gitname}-${pkgver}/plog" } build() { cd "$srcdir/${_gitname}-${pkgver}" - qmake CONFIG+=release "${srcdir}/${_gitname}-${pkgver}/GlobalProtect-openconnect.pro" - make + ./cmakew -B build + MAKEFLAGS=-j$(nproc) ./cmakew --build build } package() { cd "$srcdir/${_gitname}-${pkgver}" - make INSTALL_ROOT="$pkgdir/" install + make DESTDIR="$pkgdir/" install -C build } diff --git a/README.md b/README.md index 2b521f5..25c7bd6 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ A GlobalProtect VPN client (GUI) for Linux based on Openconnect and built with Qt5, supports SAML auth mode, inspired by [gp-saml-gui](https://github.com/dlenski/gp-saml-gui).

- +

## Features @@ -43,69 +43,60 @@ Install the [AppIndicator and KStatusNotifierItem Support](https://extensions.gn - Openconnect v8.x - Qt5, qt5-webengine, qt5-websockets -### Ubuntu -1. Install openconnect v8.x +## Build & Install - ```sh - sudo apt install openconnect - openconnect --version - ``` - - For Ubuntu 18.04, using this [dwmw2/openconnect](https://launchpad.net/~dwmw2/+archive/ubuntu/openconnect) PPA. - - ```sh - sudo add-apt-repository ppa:dwmw2/openconnect - sudo apt-get update - sudo apt install openconnect - ``` - -1. Install the Qt dependencies - - For Ubuntu 20, this should work. - - ```sh - sudo apt install qtbase5-dev libqt5websockets5-dev qtwebengine5-dev qttools5-dev debhelper - ``` - - For Ubuntu 21, you need to install the base pieces separately as QT5 is the default. - - ```sh - sudo apt install qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools libqt5websockets5-dev qtwebengine5-dev qttools5-dev debhelper - ``` - -### OpenSUSE -Install the Qt dependencies - -```sh -sudo zypper install libqt5-qtbase-devel libqt5-qtwebsockets-devel libqt5-qtwebengine-devel -``` - -### Fedora -Install the Qt dependencies: - -```sh -sudo dnf install qt5-qtbase-devel qt5-qtwebengine-devel qt5-qtwebsockets-devel -``` - -## Install - -### Install from AUR (Arch/Manjaro) - -Install [globalprotect-openconnect](https://aur.archlinux.org/packages/globalprotect-openconnect/). - -### Build from source code +Clone this repo with: ```sh git clone https://github.com/yuezk/GlobalProtect-openconnect.git cd GlobalProtect-openconnect -git submodule update --init - -# qmake or qmake-qt5 -qmake CONFIG+=release -make -sudo make install ``` -Open `GlobalProtect VPN` in the application dashboard. + +### Arch/Manjaro +Install from the [globalprotect-openconnect](https://aur.archlinux.org/packages/globalprotect-openconnect/) AUR. +### Ubuntu +For **Ubuntu 18.04**, add this [dwmw2/openconnect](https://launchpad.net/~dwmw2/+archive/ubuntu/openconnect) PPA first to install the latest openconnect. + +```sh +sudo add-apt-repository ppa:dwmw2/openconnect +sudo apt update +``` +...then build and install with: + +```sh +./scripts/install-ubuntu.sh +``` +### openSUSE + +Build and install with: + +```sh +./scripts/install-opensuse.sh +``` + +### Fedora + +Build and install with: + +```sh +./scripts/install-fedora.sh +``` + +### Other Linux + +Install the Qt5 dependencies and OpenConnect: + +- QtCore +- QtWebEngine +- QtWebSockets +- QtDBus +- openconnect v8.x + +...then build and install with: + +```sh +./scripts/install.sh +``` ### Debian package diff --git a/VERSION b/VERSION new file mode 100644 index 0000000..785cda8 --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +1.3.3 \ No newline at end of file diff --git a/cmake/Add3rdParty.cmake b/cmake/Add3rdParty.cmake new file mode 100644 index 0000000..3809a14 --- /dev/null +++ b/cmake/Add3rdParty.cmake @@ -0,0 +1,27 @@ +include(ExternalProject) + +function(add_3rdparty NAME) + set(oneValueArgs GIT_REPOSITORY GIT_TAG) + cmake_parse_arguments(add_3rdparty_args "" "${oneValueArgs}" "" ${ARGN}) + + if(EXISTS "${CMAKE_SOURCE_DIR}/3rdparty/${NAME}/CMakeLists.txt") + message(STATUS "Found third party locally for ${NAME}") + + ExternalProject_Add( + ${NAME}-${PROJECT_NAME} + PREFIX ${CMAKE_CURRENT_BINARY_DIR}/${NAME} + SOURCE_DIR "${CMAKE_SOURCE_DIR}/3rdparty/${NAME}" + INSTALL_COMMAND "" + "${add_3rdparty_args_UNPARSED_ARGUMENTS}" + ) + return() + endif() + + message(STATUS "Using ExternalProject to download ${NAME}") + ExternalProject_Add( + ${NAME}-${PROJECT_NAME} + PREFIX ${CMAKE_CURRENT_BINARY_DIR}/${NAME} + INSTALL_COMMAND "" + "${ARGN}" + ) +endfunction() diff --git a/cmakew b/cmakew new file mode 100755 index 0000000..1d73db0 --- /dev/null +++ b/cmakew @@ -0,0 +1,102 @@ +#!/bin/bash + +cmake_version="3.21.2" + +arr_cmake_v=(${cmake_version//./ }) +cmake_version_major=(${arr_cmake_v[0]}) +cmake_version_minor=(${arr_cmake_v[1]}) +cmake_version_patch=(${arr_cmake_v[2]}) + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false + +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +cmake_base="./.cmake" +cmake_bin="${cmake_base}/cmake-$cmake_version/bin/cmake" + +# download cmake if neccessary +if [ ! -f "$cmake_bin" ]; then + download_link="" + + if [ "$darwin" = true ]; then + download_link="https://cmake.org/files/v$cmake_version_major.$cmake_version_minor/cmake-$cmake_version-Darwin-x86_64.tar.gz" + else + download_link="https://github.com/Kitware/CMake/releases/download/v${cmake_version}/cmake-${cmake_version}-linux-x86_64.tar.gz" + fi + + wget -nv --show-progress "$download_link" -O "/tmp/cmake-$cmake_version.tar.gz" + mkdir -p "${cmake_base}/cmake-$cmake_version" + tar -xzf "/tmp/cmake-$cmake_version.tar.gz" -C "${cmake_base}/cmake-$cmake_version" --strip-components=1 + rm "/tmp/cmake-$cmake_version.tar.gz" +fi + +# We build the pattern for arguments to be converted via cygpath +if [ "$cygwin" = true ]; then + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + + OURCYGPATTERN="(^($ROOTDIRS))" + + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + + i=$((i+1)) + done + + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# run cmake +exec "$cmake_bin" "$@" \ No newline at end of file diff --git a/plog b/plog deleted file mode 160000 index fda4a26..0000000 --- a/plog +++ /dev/null @@ -1 +0,0 @@ -Subproject commit fda4a26c26b2d1b2beb68d7b92b56950ec2b8ad2 diff --git a/screenshot.png b/screenshot.png deleted file mode 100644 index 868eb9b10f341c54eb62853e57cababa78e57730..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24189 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 Hti%2T$B~5@ diff --git a/scripts/bump-version.sh b/scripts/bump-version.sh new file mode 100755 index 0000000..7130bb1 --- /dev/null +++ b/scripts/bump-version.sh @@ -0,0 +1,452 @@ +#!/bin/bash +# +# █▄▄ █░█ █▀▄▀█ █▀█ ▄▄ █░█ █▀▀ █▀█ █▀ █ █▀█ █▄░█ +# █▄█ █▄█ █░▀░█ █▀▀ ░░ ▀▄▀ ██▄ █▀▄ ▄█ █ █▄█ █░▀█ +# +# Description: +# - This script automates bumping the git software project's version using automation. + +# - It does several things that are typically required for releasing a Git repository, like git tagging, +# automatic updating of CHANGELOG.md, and incrementing the version number in various JSON files. + +# - Increments / suggests the current software project's version number +# - Adds a Git tag, named after the chosen version number +# - Updates CHANGELOG.md +# - Updates VERSION file +# - Commits files to a new branch +# - Pushes to remote (optionally) +# - Updates "version" : "x.x.x" tag in JSON files if [-v file1 -v file2...] argument is supplied. +# +# Usage: +# ./bump-version.sh [-v ] [-m ] [-j ] [-j ].. [-n] [-p] [-b] [-h] +# +# Options: +# -v Specify a manual version number +# -m Custom release message. +# -f Update version number inside JSON files. +# * For multiple files, add a separate -f option for each one, +# * For example: ./bump-version.sh -f src/plugin/package.json -f composer.json +# -p Push commits to remote repository, eg `-p origin` +# -n Don't perform a commit automatically. +# * You may want to do that yourself, for example. +# -b Don't create automatic `release-` branch +# -h Show help message. + +# +# Detailed notes: +# – The contents of the `VERSION` file which should be a semantic version number such as "1.2.3" +# or even "1.2.3-beta+001.ab" +# +# – It pulls a list of changes from git history & prepends to a file called CHANGELOG.md +# under the title of the new version # number, allows the user to review and update the changelist +# +# – Creates a Git tag with the version number +# +# - Creates automatic `release-` branch +# +# – Commits the new version to the current repository +# +# – Optionally pushes the commit to remote repository +# +# – Make sure to set execute permissions for the script, eg `$ chmod 755 bump-version.sh` +# +# Credits: +# – https://github.com/jv-k/bump-version +# +# - Inspired by the scripts from @pete-otaqui and @mareksuscak +# https://gist.github.com/pete-otaqui/4188238 +# https://gist.github.com/mareksuscak/1f206fbc3bb9d97dec9c +# + +NOW="$(date +'%B %d, %Y')" + +# ANSI/VT100 colours +YELLOW='\033[1;33m' +LIGHTYELLOW='\033[0;33m' +RED='\033[0;31m' +LIGHTRED='\033[1;31m' +GREEN='\033[0;32m' +LIGHTGREEN='\033[1;32m' +BLUE='\033[0;34m' +LIGHTBLUE='\033[1;34m' +PURPLE='\033[0;35m' +LIGHTPURPLE='\033[1;35m' +CYAN='\033[0;36m' +LIGHTCYAN='\033[1;36m' +WHITE='\033[1;37m' +LIGHTGRAY='\033[0;37m' +DARKGRAY='\033[1;30m' +BOLD="\033[1m" +INVERT="\033[7m" +RESET='\033[0m' + +# Default options +FLAG_JSON="false" +FLAG_PUSH="false" + +I_OK="✅"; I_STOP="🚫"; I_ERROR="❌"; I_END="👋🏻" + +S_NORM="${WHITE}" +S_LIGHT="${LIGHTGRAY}" +S_NOTICE="${GREEN}" +S_QUESTION="${YELLOW}" +S_WARN="${LIGHTRED}" +S_ERROR="${RED}" + +V_SUGGEST="0.1.0" # This is suggested in case VERSION file or user supplied version via -v is missing +GIT_MSG="" +REL_NOTE="" +REL_PREFIX="release-" +PUSH_DEST="origin" + +# Show credits & help +usage() { + echo -e "$GREEN"\ + "\n █▄▄ █░█ █▀▄▀█ █▀█ ▄▄ █░█ █▀▀ █▀█ █▀ █ █▀█ █▄░█ "\ + "\n █▄█ █▄█ █░▀░█ █▀▀ ░░ ▀▄▀ ██▄ █▀▄ ▄█ █ █▄█ █░▀█ "\ + "\n\t\t\t\t\t$LIGHTGRAY v${SCRIPT_VER}"\ + + echo -e " ${S_NORM}${BOLD}Usage:${RESET}"\ + "\n $0 [-v ] [-m ] [-j ] [-j ].. [-n] [-p] [-h]" 1>&2; + + echo -e "\n ${S_NORM}${BOLD}Options:${RESET}" + echo -e " $S_WARN-v$S_NORM \tSpecify a manual version number" + echo -e " $S_WARN-m$S_NORM \tCustom release message." + echo -e " $S_WARN-f$S_NORM \tUpdate version number inside JSON files."\ + "\n\t\t\t* For multiple files, add a separate -f option for each one,"\ + "\n\t\t\t* For example: ./bump-version.sh -f src/plugin/package.json -f composer.json" + echo -e " $S_WARN-p$S_NORM \t\t\tPush commits to ORIGIN. " + echo -e " $S_WARN-n$S_NORM \t\t\tDon't perform a commit automatically. "\ + "\n\t\t\t* You may want to do that manually after checking everything, for example." + echo -e " $S_WARN-b$S_NORM \t\t\tDon't create automatic \`release-\` branch" + echo -e " $S_WARN-h$S_NORM \t\t\tShow this help message. " + echo -e "\n ${S_NORM}${BOLD}Author:$S_LIGHT https://github.com/jv-t/bump-version $RESET\n" + +} + +# If there are no commits in repo, quit, because you can't tag with zero commits. +check-commits-exist() { + git rev-parse HEAD &> /dev/null + if [ ! "$?" -eq 0 ]; then + echo -e "\n${I_STOP} ${S_ERROR}Your current branch doesn't have any commits yet. Can't tag without at least one commit." >&2 + echo + exit 1 + fi +} + +get-commit-msg() { + echo Bumped $([ -n "${V_PREV}" ] && echo "${V_PREV} –>" || echo "to ") "$V_USR_INPUT" +} + +exit_abnormal() { + echo -e " ${S_LIGHT}––––––" + usage # Show help + exit 1 +} + +# Process script options +process-arguments() { + local OPTIONS OPTIND OPTARG + + # Get positional parameters + JSON_FILES=( ) + while getopts ":v:p:m:f:hbn" OPTIONS; do # Note: Adding the first : before the flags takes control of flags and prevents default error msgs. + case "$OPTIONS" in + h ) + # Show help + exit_abnormal + ;; + v ) + # User has supplied a version number + V_USR_SUPPLIED=$OPTARG + ;; + m ) + REL_NOTE=$OPTARG + # Custom release note + echo -e "\n${S_LIGHT}Option set: ${S_NOTICE}Release note:" ${S_NORM}"'"$REL_NOTE"'" + ;; + f ) + FLAG_JSON=true + echo -e "\n${S_LIGHT}Option set: ${S_NOTICE}JSON file via [-f]: <${S_NORM}${OPTARG}${S_LIGHT}>" + # Store JSON filenames(s) + JSON_FILES+=($OPTARG) + ;; + p ) + FLAG_PUSH=true + PUSH_DEST=${OPTARG} # Replace default with user input + echo -e "\n${S_LIGHT}Option set: ${S_NOTICE}Pushing to <${S_NORM}${PUSH_DEST}${S_LIGHT}>, as the last action in this script." + ;; + n ) + FLAG_NOCOMMIT=true + echo -e "\n${S_LIGHT}Option set: ${S_NOTICE}Disable commit after tagging." + ;; + b ) + FLAG_NOBRANCH=true + echo -e "\n${S_LIGHT}Option set: ${S_NOTICE}Disable committing to new branch." + ;; + \? ) + echo -e "\n${I_ERROR}${S_ERROR} Invalid option: ${S_WARN}-$OPTARG" >&2 + echo + exit_abnormal + ;; + : ) + echo -e "\n${I_ERROR}${S_ERROR} Option ${S_WARN}-$OPTARG ${S_ERROR}requires an argument." >&2 + echo + exit_abnormal + ;; + esac + done +} + +# Suggests version from VERSION file, or grabs from user supplied -v . +# If none is set, suggest default from options. +process-version() { + if [ -f VERSION ] && [ -s VERSION ]; then + V_PREV=`cat VERSION` + + echo -e "\n${S_NOTICE}Current version from <${S_NORM}VERSION${S_NOTICE}> file: ${S_NORM}$V_PREV" + + # Suggest incremented value from VERSION file + V_PREV_LIST=(`echo $V_PREV | tr '.' ' '`) + V_MAJOR=${V_PREV_LIST[0]}; V_MINOR=${V_PREV_LIST[1]}; V_PATCH=${V_PREV_LIST[2]}; + + # Test if V_PATCH is a number, then increment it. Otherwise, do nothing + if [ "$V_PATCH" -eq "$V_PATCH" ] 2>/dev/null; then # discard stderr (2) output to black hole (suppress it) + V_PATCH=$((V_PATCH + 1)) # Increment + fi + + V_SUGGEST="$V_MAJOR.$V_MINOR.$V_PATCH" + else + echo -ne "\n${S_WARN}The [${S_NORM}VERSION${S_WARN}] " + if [ ! -f VERSION ]; then + echo "file was not found."; + elif [ ! -s VERSION ]; then + echo "file is empty."; + fi + fi + + # If a version number is supplied by the user with [-v ], then use it + if [ -n "$V_USR_SUPPLIED" ]; then + echo -e "\n${S_NOTICE}You selected version using [-v]:" "${S_WARN}${V_USR_SUPPLIED}" + V_USR_INPUT="${V_USR_SUPPLIED}" + else + echo -ne "\n${S_QUESTION}Enter a new version number [${S_NORM}$V_SUGGEST${S_QUESTION}]: " + echo -ne "$S_WARN" + read V_USR_INPUT + + if [ "$V_USR_INPUT" = "" ]; then + V_USR_INPUT="${V_SUGGEST}" + fi + fi + + # echo -e "${S_NOTICE}Setting version to [${S_NORM}${V_USR_INPUT}${S_NOTICE}] ...." +} + +# Only tag if tag doesn't already exist +check-tag-exists() { + TAG_CHECK_EXISTS=`git tag -l v"$V_USR_INPUT"` + if [ -n "$TAG_CHECK_EXISTS" ]; then + echo -e "\n${I_STOP} ${S_ERROR}Error: A release with that tag version number already exists!\n" + exit 0 + fi +} + +# $1 : version +# $2 : release note +tag() { + if [ -z "$2" ]; then + # Default release note + git tag -a "v$1" -m "Tag version $1." + else + # Custom release note + git tag -a "v$1" -m "$2" + fi + echo -e "\n${I_OK} ${S_NOTICE}Added GIT tag" +} + +# Change `version:` value in JSON files, like packager.json, composer.json, etc +bump-json-files() { + if [ "$FLAG_JSON" != true ]; then return; fi + + JSON_PROCESSED=( ) # holds filenames after they've been changed + + for FILE in "${JSON_FILES[@]}"; do + if [ -f $FILE ]; then + # Get the existing version number + V_OLD=$( sed -n 's/.*"version": "\(.*\)",/\1/p' $FILE ) + + if [ "$V_OLD" = "$V_USR_INPUT" ]; then + echo -e "\n${S_WARN}File <${S_NORM}$FILE${S_WARN}> already contains version: ${S_NORM}$V_OLD" + else + # Write to output file + FILE_MSG=`sed -i .temp "s/\"version\": \"$V_OLD\"/\"version\": \"$V_USR_INPUT\"/g" $FILE 2>&1` + if [ "$?" -eq 0 ]; then + echo -e "\n${I_OK} ${S_NOTICE}Updated file: <${S_NOTICE}$FILE${S_LIGHT}> from ${S_NORM}$V_OLD -> $V_USR_INPUT" + rm -f ${FILE}.temp + # Add file change to commit message: + GIT_MSG+="${GIT_MSG}Updated $FILE, " + else + echo -e "\n${I_STOP} ${S_ERROR}Error\n$PUSH_MSG\n" + fi + fi + + JSON_PROCESSED+=($FILE) + else + echo -e "\n${S_WARN}File <${S_NORM}$FILE${S_WARN}> not found." + fi + done + # Stage files that were changed: + [ -n "${JSON_PROCESSED}" ] && git add "${JSON_PROCESSED[@]}" +} + +# Handle VERSION file +do-versionfile() { + [ -f VERSION ] && ACTION_MSG="Updated" || ACTION_MSG="Created" + + GIT_MSG+="${ACTION_MSG} VERSION, " + echo $V_USR_INPUT > VERSION # Create file + echo -e "\n${I_OK} ${S_NOTICE}${ACTION_MSG} [${S_NORM}VERSION${S_NOTICE}] file" + + # Stage file for commit + git add VERSION +} + +# Dump git log history to CHANGELOG.md +do-changelog() { + + # Log latest commits to CHANGELOG.md: + # Get latest commits + LOG_MSG=`git log --pretty=format:"- %s" $([ -n "$V_PREV" ] && echo "v${V_PREV}...HEAD") 2>&1` + if [ ! "$?" -eq 0 ]; then + echo -e "\n${I_STOP} ${S_ERROR}Error getting commit history for logging to CHANGELOG.\n$LOG_MSG\n" + exit 1 + fi + + [ -f CHANGELOG.md ] && ACTION_MSG="Updated" || ACTION_MSG="Created" + # Add info to commit message for later: + GIT_MSG+="${ACTION_MSG} CHANGELOG.md, " + + # Add heading + echo "## $V_USR_INPUT ($NOW)" > tmpfile + + # Log the bumping commit: + # - The final commit is done after do-changelog(), so we need to create the log entry for it manually: + echo "- ${GIT_MSG}$(get-commit-msg)" >> tmpfile + # Add previous commits + [ -n "$LOG_MSG" ] && echo "$LOG_MSG" >> tmpfile + + echo -en "\n" >> tmpfile + + if [ -f CHANGELOG.md ]; then + # Append existing log + cat CHANGELOG.md >> tmpfile + else + echo -e "\n${S_WARN}A [${S_NORM}CHANGELOG.md${S_WARN}] file was not found." + fi + + mv tmpfile CHANGELOG.md + + # User prompts + echo -e "\n${I_OK} ${S_NOTICE}${ACTION_MSG} [${S_NORM}CHANGELOG.md${S_NOTICE}] file" + # Pause & allow user to open and edit the file: + echo -en "\n${S_QUESTION}Make adjustments to [${S_NORM}CHANGELOG.md${S_QUESTION}] if required now. Press to continue." + read + + # Stage log file, to commit later + git add CHANGELOG.md +} + +# +check-branch-exist() { + [ "$FLAG_NOBRANCH" = true ] && return + + BRANCH_MSG=`git rev-parse --verify "${REL_PREFIX}${V_USR_INPUT}" 2>&1` + if [ "$?" -eq 0 ]; then + echo -e "\n${I_STOP} ${S_ERROR}Error: Branch <${S_NORM}${REL_PREFIX}${V_USR_INPUT}${S_ERROR}> already exists!\n" + exit 1 + fi +} + +# +do-branch() { + [ "$FLAG_NOBRANCH" = true ] && return + + echo -e "\n${S_NOTICE}Creating new release branch..." + + BRANCH_MSG=`git branch "${REL_PREFIX}${V_USR_INPUT}" 2>&1` + if [ ! "$?" -eq 0 ]; then + echo -e "\n${I_STOP} ${S_ERROR}Error\n$BRANCH_MSG\n" + exit 1 + else + BRANCH_MSG=`git checkout "${REL_PREFIX}${V_USR_INPUT}" 2>&1` + echo -e "\n${I_OK} ${S_NOTICE}${BRANCH_MSG}" + fi + + # REL_PREFIX +} + +# Stage & commit all files modified by this script +do-commit() { + [ "$FLAG_NOCOMMIT" = true ] && return + + GIT_MSG+="$(get-commit-msg)" + echo -e "\n${S_NOTICE}Committing..." + COMMIT_MSG=`git commit -m "${GIT_MSG}" 2>&1` + if [ ! "$?" -eq 0 ]; then + echo -e "\n${I_STOP} ${S_ERROR}Error\n$COMMIT_MSG\n" + exit 1 + else + echo -e "\n${I_OK} ${S_NOTICE}$COMMIT_MSG" + fi +} + +# Pushes files + tags to remote repo. Changes are staged by earlier functions +do-push() { + [ "$FLAG_NOCOMMIT" = true ] && return + + if [ "$FLAG_PUSH" = true ]; then + CONFIRM="Y" + else + echo -ne "\n${S_QUESTION}Push tags to <${S_NORM}${PUSH_DEST}${S_QUESTION}>? [${S_NORM}N/y${S_QUESTION}]: " + read CONFIRM + fi + + case "$CONFIRM" in + [yY][eE][sS]|[yY] ) + echo -e "\n${S_NOTICE}Pushing files + tags to <${S_NORM}${PUSH_DEST}${S_NOTICE}>..." + PUSH_MSG=`git push "${PUSH_DEST}" v"$V_USR_INPUT" 2>&1` # Push new tag + if [ ! "$?" -eq 0 ]; then + echo -e "\n${I_STOP} ${S_WARN}Warning\n$PUSH_MSG" + # exit 1 + else + echo -e "\n${I_OK} ${S_NOTICE}$PUSH_MSG" + fi + ;; + esac +} + +#### Initiate Script ########################### + +check-commits-exist + +# Process and prepare +process-arguments "$@" +process-version + +check-branch-exist +check-tag-exists + +echo -e "\n${S_LIGHT}––––––" + +# Update files +bump-json-files +do-versionfile +# do-changelog +# do-branch +do-commit +tag "${V_USR_INPUT}" "${REL_NOTE}" +do-push + +echo -e "\n${S_LIGHT}––––––" +echo -e "\n${I_OK} ${S_NOTICE}"Bumped $([ -n "${V_PREV}" ] && echo "${V_PREV} –>" || echo "to ") "$V_USR_INPUT" +echo -e "\n${GREEN}Done ${I_END}\n" \ No newline at end of file diff --git a/scripts/install-fedora.sh b/scripts/install-fedora.sh new file mode 100755 index 0000000..37bab58 --- /dev/null +++ b/scripts/install-fedora.sh @@ -0,0 +1,9 @@ +#!/bin/bash -e + +sudo dnf install -y \ + qt5-qtbase-devel \ + qt5-qtwebengine-devel \ + qt5-qtwebsockets-devel \ + openconnect + +./scripts/install.sh \ No newline at end of file diff --git a/scripts/install-opensuse.sh b/scripts/install-opensuse.sh new file mode 100755 index 0000000..3bd78c5 --- /dev/null +++ b/scripts/install-opensuse.sh @@ -0,0 +1,9 @@ +#!/bin/bash -e + +sudo zypper install -y \ + libqt5-qtbase-devel \ + libqt5-qtwebsockets-devel \ + libqt5-qtwebengine-devel \ + openconnect + +./scripts/install.sh \ No newline at end of file diff --git a/scripts/install-ubuntu.sh b/scripts/install-ubuntu.sh new file mode 100755 index 0000000..663c8fc --- /dev/null +++ b/scripts/install-ubuntu.sh @@ -0,0 +1,11 @@ +#!/bin/bash -e + +sudo apt update +sudo apt install -y \ + build-essential \ + qtbase5-dev \ + libqt5websockets5-dev \ + qtwebengine5-dev \ + openconnect + +./scripts/install.sh \ No newline at end of file diff --git a/scripts/install.sh b/scripts/install.sh new file mode 100755 index 0000000..e6aa582 --- /dev/null +++ b/scripts/install.sh @@ -0,0 +1,10 @@ +#!/bin/bash -e + +./cmakew -B build -DCMAKE_BUILD_TYPE=Release +MAKEFLAGS=-j$(nproc) ./cmakew --build build +sudo ./cmakew --install build + +sudo systemctl daemon-reload +sudo systemctl restart gpservice.service + +echo -e "\nDone. You can launch the GlobalProtect VPN client from the application dashboard.\n" \ No newline at end of file diff --git a/singleapplication b/singleapplication deleted file mode 160000 index 0f6695e..0000000 --- a/singleapplication +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 0f6695e2a9d8fdaa336e7ad941855c46c61f218a diff --git a/version.h.in b/version.h.in new file mode 100644 index 0000000..e275553 --- /dev/null +++ b/version.h.in @@ -0,0 +1 @@ +#define VERSION "@GlobalProtect-openconnect_VERSION@" \ No newline at end of file From 452fe2f1894fb3085216e3a464d044a752023203 Mon Sep 17 00:00:00 2001 From: Kevin Yue Date: Sun, 19 Sep 2021 15:40:20 +0800 Subject: [PATCH 4/4] update doc --- README.md | 5 ++++- scripts/install.sh | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 25c7bd6..45286ce 100644 --- a/README.md +++ b/README.md @@ -53,8 +53,11 @@ cd GlobalProtect-openconnect ``` ### Arch/Manjaro + Install from the [globalprotect-openconnect](https://aur.archlinux.org/packages/globalprotect-openconnect/) AUR. -### Ubuntu + +### Ubuntu/Mint + For **Ubuntu 18.04**, add this [dwmw2/openconnect](https://launchpad.net/~dwmw2/+archive/ubuntu/openconnect) PPA first to install the latest openconnect. ```sh diff --git a/scripts/install.sh b/scripts/install.sh index e6aa582..672c0a1 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -7,4 +7,4 @@ sudo ./cmakew --install build sudo systemctl daemon-reload sudo systemctl restart gpservice.service -echo -e "\nDone. You can launch the GlobalProtect VPN client from the application dashboard.\n" \ No newline at end of file +echo -e "\nSuccess. You can launch the GlobalProtect VPN client from the application dashboard.\n" \ No newline at end of file