mirror of
				https://github.com/yuezk/GlobalProtect-openconnect.git
				synced 2025-05-20 07:26:58 -04:00 
			
		
		
		
	Compare commits
	
		
			38 Commits
		
	
	
		
			v1.4.8
			...
			e8259b841b
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | e8259b841b | ||
|  | 939f2bd94a | ||
|  | abffa21268 | ||
|  | 99342372d2 | ||
|  | cd8d794655 | ||
|  | 705b03c0bb | ||
|  | 7bef2ccc68 | ||
|  | bffc5d733b | ||
|  | 8ca2610550 | ||
|  | acf184134a | ||
|  | 4a3f74f1c3 | ||
|  | b39983a0f8 | ||
|  | d6fa32d95d | ||
|  | 7c299f6e68 | ||
|  | 25e8ccd07e | ||
|  | 092123b075 | ||
|  | feb2956cc1 | ||
|  | d356839859 | ||
|  | 2ff39fd14e | ||
|  | c3d300c807 | ||
|  | ef43d10a70 | ||
|  | bd73466e48 | ||
|  | cc2c0ae34e | ||
|  | 9207f7a798 | ||
|  | 2069b7fd8e | ||
|  | f552ef6204 | ||
|  | 2761f7521a | ||
|  | c3939a774b | ||
|  | 49e5242bf2 | ||
|  | 3181d37b20 | ||
|  | 6d788a5e91 | ||
|  | 74c7549444 | ||
|  | c52ccb87f1 | ||
|  | fab25848e1 | ||
|  | 75a24c89cd | ||
|  | 15a73b7dba | ||
|  | 0adeaf9c28 | ||
|  | fe64b2cd19 | 
							
								
								
									
										2
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							| @@ -31,6 +31,8 @@ jobs: | ||||
|       - name: Build | ||||
|         run: | | ||||
|           ./scripts/install-ubuntu.sh | ||||
|           # assert no library missing | ||||
|           test $(ldd $(which gpclient) | grep 'not found' | wc -l) -eq 0 | ||||
|  | ||||
|   snapshot-archive-all: | ||||
|     if: ${{ github.event_name != 'pull_request' && github.ref == 'refs/heads/develop' }} | ||||
|   | ||||
							
								
								
									
										2
									
								
								.github/workflows/pr.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/pr.yml
									
									
									
									
										vendored
									
									
								
							| @@ -29,3 +29,5 @@ jobs: | ||||
|       - name: Build | ||||
|         run: | | ||||
|           ./scripts/install-ubuntu.sh | ||||
|           # assert no library missing | ||||
|           test $(ldd $(which gpclient) | grep 'not found' | wc -l) -eq 0 | ||||
|   | ||||
							
								
								
									
										3
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							| @@ -5,3 +5,6 @@ | ||||
| [submodule "plog"] | ||||
| 	path = 3rdparty/plog | ||||
| 	url = https://github.com/SergiusTheBest/plog.git | ||||
| [submodule "3rdparty/qtkeychain"] | ||||
| 	path = 3rdparty/qtkeychain | ||||
| 	url = git@github.com:frankosterfeld/qtkeychain.git | ||||
|   | ||||
							
								
								
									
										1
									
								
								3rdparty/qtkeychain
									
									
									
									
										vendored
									
									
										Submodule
									
								
							
							
								
								
								
								
								
							
						
						
									
										1
									
								
								3rdparty/qtkeychain
									
									
									
									
										vendored
									
									
										Submodule
									
								
							 Submodule 3rdparty/qtkeychain added at f197cdb935
									
								
							| @@ -30,6 +30,8 @@ find_package(Qt5 REQUIRED COMPONENTS | ||||
|     DBus | ||||
| ) | ||||
|  | ||||
| find_package(Qt5Keychain REQUIRED) | ||||
|  | ||||
| add_subdirectory(3rdparty/qt-unix-signals) | ||||
| add_subdirectory(3rdparty/inih) | ||||
| add_subdirectory(GPService) | ||||
|   | ||||
| @@ -17,6 +17,7 @@ add_executable(gpclient | ||||
|     cdpcommand.cpp | ||||
|     cdpcommandmanager.cpp | ||||
|     enhancedwebview.cpp | ||||
|     enhancedwebpage.cpp | ||||
|     gatewayauthenticator.cpp | ||||
|     gatewayauthenticatorparams.cpp | ||||
|     gpgateway.cpp | ||||
| @@ -71,7 +72,10 @@ 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}) | ||||
| add_dependencies(gpclient | ||||
|     SingleApplication-${PROJECT_NAME} | ||||
|     plog-${PROJECT_NAME} | ||||
| ) | ||||
|  | ||||
| target_include_directories(gpclient PRIVATE | ||||
|     ${CMAKE_BINARY_DIR} | ||||
| @@ -79,6 +83,7 @@ target_include_directories(gpclient PRIVATE | ||||
|     ${CMAKE_CURRENT_BINARY_DIR} | ||||
|     ${SingleApplication_INCLUDE_DIR} | ||||
|     ${plog_INCLUDE_DIR} | ||||
|     ${QTKEYCHAIN_INCLUDE_DIRS}/qt5keychain | ||||
| ) | ||||
|  | ||||
| target_link_libraries(gpclient | ||||
| @@ -90,6 +95,8 @@ target_link_libraries(gpclient | ||||
|     Qt5::WebEngineWidgets | ||||
|     Qt5::DBus | ||||
|     QtSignals | ||||
|     ${QTKEYCHAIN_LIBRARIES} | ||||
|     inih | ||||
| ) | ||||
|  | ||||
| if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 8.0 AND CMAKE_BUILD_TYPE STREQUAL Release) | ||||
|   | ||||
							
								
								
									
										8
									
								
								GPClient/enhancedwebpage.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								GPClient/enhancedwebpage.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| #include "enhancedwebpage.h" | ||||
| #include <QWebEngineCertificateError> | ||||
| #include <plog/Log.h> | ||||
|  | ||||
| bool EnhancedWebPage::certificateError(const QWebEngineCertificateError &certificateError) { | ||||
|     LOGI << "An error occurred during certificate verification for " << certificateError.url().toString() << "; " << certificateError.errorDescription(); | ||||
|     return certificateError.isOverridable(); | ||||
| }; | ||||
							
								
								
									
										12
									
								
								GPClient/enhancedwebpage.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								GPClient/enhancedwebpage.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| #ifndef ENHANCEDWEBPAGE_H | ||||
| #define ENHANCEDWEBPAGE_H | ||||
|  | ||||
| #include <QtWebEngineWidgets/qwebenginepage.h> | ||||
|  | ||||
| class EnhancedWebPage : public QWebEnginePage | ||||
| { | ||||
| protected: | ||||
|     bool certificateError(const QWebEngineCertificateError &certificateError) override; | ||||
| }; | ||||
|  | ||||
| #endif // !ECHANCEDWEBPAG | ||||
| @@ -1,6 +1,7 @@ | ||||
| #include <QtCore/QProcessEnvironment> | ||||
| #include <QtWebEngineWidgets/QWebEngineView> | ||||
|  | ||||
| #include "enhancedwebpage.h" | ||||
| #include "enhancedwebview.h" | ||||
| #include "cdpcommandmanager.h" | ||||
|  | ||||
| @@ -14,6 +15,7 @@ EnhancedWebView::EnhancedWebView(QWidget *parent) | ||||
|  | ||||
| void EnhancedWebView::initialize() | ||||
| { | ||||
|     setPage(new EnhancedWebPage()); | ||||
|     auto port = QProcessEnvironment::systemEnvironment().value(ENV_CDP_PORT); | ||||
|     cdp->initialize("http://127.0.0.1:" + port + "/json"); | ||||
| } | ||||
|   | ||||
| @@ -151,7 +151,7 @@ void GatewayAuthenticator::samlAuth(QString samlMethod, QString samlRequest, QSt | ||||
| { | ||||
|     LOGI << "Trying to perform SAML login with saml-method " << samlMethod; | ||||
|  | ||||
|     auto *loginWindow = new SAMLLoginWindow; | ||||
|     auto *loginWindow = new SAMLLoginWindow(gateway); | ||||
|  | ||||
|     connect(loginWindow, &SAMLLoginWindow::success, [this, loginWindow](const QMap<QString, QString> &samlResult) { | ||||
|         this->onSAMLLoginSuccess(samlResult); | ||||
|   | ||||
| @@ -64,4 +64,3 @@ void GatewayAuthenticatorParams::setInputStr(const QString &inputStr) | ||||
| { | ||||
|     m_inputStr = inputStr; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -40,14 +40,6 @@ GPClient::GPClient(QWidget *parent, IVpn *vpn) | ||||
|     initVpnStatus(); | ||||
| } | ||||
|  | ||||
| GPClient::~GPClient() | ||||
| { | ||||
|     delete ui; | ||||
|     delete vpn; | ||||
|     delete settingsDialog; | ||||
|     delete settingsButton; | ||||
| } | ||||
|  | ||||
| void GPClient::setupSettings() | ||||
| { | ||||
|     settingsButton = new QPushButton(this); | ||||
| @@ -69,12 +61,14 @@ void GPClient::setupSettings() | ||||
| void GPClient::onSettingsButtonClicked() | ||||
| { | ||||
|     settingsDialog->setClientos(settings::get("clientos", "Linux").toString()); | ||||
|     settingsDialog->setOsVersion(settings::get("os-version", QSysInfo::prettyProductName()).toString()); | ||||
|     settingsDialog->show(); | ||||
| } | ||||
|  | ||||
| void GPClient::onSettingsAccepted() | ||||
| { | ||||
|     settings::save("clientos", settingsDialog->clientos()); | ||||
|     settings::save("os-version", settingsDialog->osVersion()); | ||||
| } | ||||
|  | ||||
| void GPClient::on_connectButton_clicked() | ||||
| @@ -112,7 +106,7 @@ void GPClient::initSystemTrayIcon() | ||||
|     connectAction = contextMenu->addAction(QIcon::fromTheme("preferences-system-network"), "Connect", this, &GPClient::doConnect); | ||||
|     contextMenu->addMenu(gatewaySwitchMenu); | ||||
|     contextMenu->addSeparator(); | ||||
|     clearAction = contextMenu->addAction(QIcon::fromTheme("edit-clear"), "Reset", this, &GPClient::clearSettings); | ||||
|     clearAction = contextMenu->addAction(QIcon::fromTheme("edit-clear"), "Reset", this, &GPClient::reset); | ||||
|     quitAction = contextMenu->addAction(QIcon::fromTheme("application-exit"), "Quit", this, &GPClient::quit); | ||||
|  | ||||
|     systemTrayIcon->show(); | ||||
| @@ -345,7 +339,7 @@ void GPClient::onPortalFail(const QString &msg) | ||||
|  | ||||
| void GPClient::tryGatewayLogin() | ||||
| { | ||||
|     LOGI << "Try to preform login on the the gateway interface..."; | ||||
|     LOGI << "Try to perform login on the the gateway interface..."; | ||||
|  | ||||
|     // Treat the portal input as the gateway address | ||||
|     GPGateway g; | ||||
| @@ -446,8 +440,14 @@ bool GPClient::connected() const | ||||
|  | ||||
| QList<GPGateway> GPClient::allGateways() const | ||||
| { | ||||
|     const QString gatewaysJson = settings::get(portal() + "_gateways").toString(); | ||||
|     return GPGateway::fromJson(gatewaysJson); | ||||
|  | ||||
|     QList<GPGateway> gateways; | ||||
|  | ||||
|     for (auto g :settings::get_all("_gateways$") ){ | ||||
|  | ||||
|     	gateways.append(GPGateway::fromJson(settings::get(g).toString())); | ||||
|     } | ||||
|     return gateways; | ||||
| } | ||||
|  | ||||
| void GPClient::setAllGateways(QList<GPGateway> gateways) | ||||
| @@ -475,10 +475,11 @@ void GPClient::setCurrentGateway(const GPGateway gateway) | ||||
|     LOGI << "Updating the current gateway to " << gateway.name(); | ||||
|  | ||||
|     settings::save(portal() + "_selectedGateway", gateway.name()); | ||||
|     ui->portalInput->setText(gateway.address()); | ||||
|     populateGatewayMenu(); | ||||
| } | ||||
|  | ||||
| void GPClient::clearSettings() | ||||
| void GPClient::reset() | ||||
| { | ||||
|     settings::clear(); | ||||
|     populateGatewayMenu(); | ||||
|   | ||||
| @@ -21,7 +21,6 @@ class GPClient : public QMainWindow | ||||
|  | ||||
| public: | ||||
|     GPClient(QWidget *parent, IVpn *vpn); | ||||
|     ~GPClient(); | ||||
|  | ||||
|     void activate(); | ||||
|     void quit(); | ||||
| @@ -33,6 +32,7 @@ public: | ||||
|     void setCurrentGateway(const GPGateway gateway); | ||||
|  | ||||
|     void doConnect(); | ||||
|     void reset(); | ||||
|  | ||||
| private slots: | ||||
|     void onSettingsButtonClicked(); | ||||
| @@ -81,8 +81,6 @@ private: | ||||
|     SettingsDialog *settingsDialog; | ||||
|     QPushButton *settingsButton; | ||||
|  | ||||
|     GatewayAuthenticator *gatewayAuthenticator; | ||||
|  | ||||
|     bool isQuickConnect { false }; | ||||
|     bool isSwitchingGateway { false }; | ||||
|     PortalConfigResponse portalConfig; | ||||
| @@ -102,7 +100,5 @@ private: | ||||
|  | ||||
|     QList<GPGateway> allGateways() const; | ||||
|     void setAllGateways(QList<GPGateway> gateways); | ||||
|  | ||||
|     void clearSettings(); | ||||
| }; | ||||
| #endif // GPCLIENT_H | ||||
|   | ||||
| @@ -9,9 +9,12 @@ | ||||
| #include <plog/Log.h> | ||||
| #include <QWebEngineProfile> | ||||
| #include <QWebEngineCookieStore> | ||||
| #include <keychain.h> | ||||
|  | ||||
| #include "gphelper.h" | ||||
|  | ||||
| using namespace QKeychain; | ||||
|  | ||||
| QNetworkAccessManager* gpclient::helper::networkManager = new QNetworkAccessManager; | ||||
|  | ||||
| QNetworkReply* gpclient::helper::createRequest(QString url, QByteArray params) | ||||
| @@ -115,6 +118,12 @@ QVariant gpclient::helper::settings::get(const QString &key, const QVariant &def | ||||
|     return _settings->value(key, defaultValue); | ||||
| } | ||||
|  | ||||
| QStringList gpclient::helper::settings::get_all(const QString &key, const QVariant &defaultValue) | ||||
| { | ||||
| 	QRegularExpression re(key); | ||||
| 	return 	_settings->allKeys().filter(re); | ||||
| } | ||||
|  | ||||
| void gpclient::helper::settings::save(const QString &key, const QVariant &value) | ||||
| { | ||||
|     _settings->setValue(key, value); | ||||
| @@ -132,3 +141,38 @@ void gpclient::helper::settings::clear() | ||||
|  | ||||
|     QWebEngineProfile::defaultProfile()->cookieStore()->deleteAllCookies(); | ||||
| } | ||||
|  | ||||
|  | ||||
| bool gpclient::helper::settings::secureSave(const QString &key, const QString &value) { | ||||
|     WritePasswordJob job( QLatin1String("gpclient") ); | ||||
|     job.setAutoDelete( false ); | ||||
|     job.setKey( key ); | ||||
|     job.setTextData( value ); | ||||
|     QEventLoop loop; | ||||
|     job.connect( &job, SIGNAL(finished(QKeychain::Job*)), &loop, SLOT(quit()) ); | ||||
|     job.start(); | ||||
|     loop.exec(); | ||||
|     if ( job.error() ) { | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| bool gpclient::helper::settings::secureGet(const QString &key, QString &value) { | ||||
|     ReadPasswordJob job( QLatin1String("gpclient") ); | ||||
|     job.setAutoDelete( false ); | ||||
|     job.setKey( key ); | ||||
|     QEventLoop loop; | ||||
|     job.connect( &job, SIGNAL(finished(QKeychain::Job*)), &loop, SLOT(quit()) ); | ||||
|     job.start(); | ||||
|     loop.exec(); | ||||
|  | ||||
|     const QString pw = job.textData(); | ||||
|     if ( job.error() ) { | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     value = pw; | ||||
|     return true; | ||||
| } | ||||
|   | ||||
| @@ -34,8 +34,12 @@ namespace gpclient { | ||||
|             static const QStringList reservedKeys {"extraArgs", "clientos"}; | ||||
|  | ||||
|             QVariant get(const QString &key, const QVariant &defaultValue = QVariant()); | ||||
|             QStringList get_all(const QString &key, const QVariant &defaultValue = QVariant()); | ||||
|             void save(const QString &key, const QVariant &value); | ||||
|             void clear(); | ||||
|  | ||||
|             bool secureSave(const QString &key, const QString &value); | ||||
|             bool secureGet(const QString &key, QString &value); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,6 +1,9 @@ | ||||
| #include <QtCore/QUrlQuery> | ||||
|  | ||||
| #include "loginparams.h" | ||||
| #include "gphelper.h" | ||||
|  | ||||
| using namespace gpclient::helper; | ||||
|  | ||||
| LoginParams::LoginParams(const QString clientos) | ||||
| { | ||||
| @@ -14,13 +17,18 @@ LoginParams::LoginParams(const QString clientos) | ||||
|     params.addQueryItem("ok", "Login"); | ||||
|     params.addQueryItem("direct", "yes"); | ||||
|     params.addQueryItem("clientVer", "4100"); | ||||
|     params.addQueryItem("os-version", QUrl::toPercentEncoding(QSysInfo::prettyProductName())); | ||||
|  | ||||
|     // add the clientos parameter if not empty | ||||
|     if (!clientos.isEmpty()) { | ||||
|         params.addQueryItem("clientos", clientos); | ||||
|     } | ||||
|  | ||||
|     auto osVersion = settings::get("os-version", "").toString(); | ||||
|     if (osVersion.isEmpty()) { | ||||
|         osVersion = QSysInfo::prettyProductName(); | ||||
|     } | ||||
|     params.addQueryItem("os-version", QUrl::toPercentEncoding(osVersion)); | ||||
|  | ||||
|     params.addQueryItem("portal-userauthcookie", ""); | ||||
|     params.addQueryItem("portal-prelogonuserauthcookie", ""); | ||||
|     params.addQueryItem("prelogin-cookie", ""); | ||||
|   | ||||
| @@ -46,6 +46,7 @@ int main(int argc, char *argv[]) | ||||
|       {"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."}, | ||||
|       {"start-minimized", "Launch the client minimized."}, | ||||
|       {"reset", "Reset the client's settings."}, | ||||
|     }); | ||||
|     parser.process(app); | ||||
|  | ||||
| @@ -55,7 +56,6 @@ int main(int argc, char *argv[]) | ||||
|       ? 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); | ||||
|     parser.isSet("start-minimized") ? w.showMinimized() : w.show(); | ||||
|  | ||||
|     if (positional.size() > 0) { | ||||
|       w.portal(positional.at(0)); | ||||
| @@ -76,11 +76,20 @@ int main(int argc, char *argv[]) | ||||
|     sigwatch.watchForSignal(SIGHUP); | ||||
|     QObject::connect(&sigwatch, &UnixSignalWatcher::unixSignal, &w, &GPClient::quit); | ||||
|  | ||||
|     if (parser.isSet("json")) { | ||||
|         QObject::connect(static_cast<VpnJson*>(vpn), &VpnJson::connected, &w, &GPClient::quit); | ||||
|     } | ||||
|  | ||||
|     if (parser.isSet("reset")) { | ||||
|         w.reset(); | ||||
|     } | ||||
|  | ||||
|     if (parser.isSet("now")) { | ||||
|       w.doConnect(); | ||||
|     } | ||||
|     if (parser.isSet("json")) { | ||||
|       QObject::connect(static_cast<VpnJson*>(vpn), &VpnJson::connected, &w, &GPClient::quit); | ||||
|     } else if (parser.isSet("start-minimized")) { | ||||
|       w.showMinimized(); | ||||
|     } else { | ||||
|       w.show(); | ||||
|     } | ||||
|  | ||||
|     return app.exec(); | ||||
|   | ||||
| @@ -32,7 +32,7 @@ void PortalAuthenticator::authenticate() | ||||
| { | ||||
|     attempts++; | ||||
|  | ||||
|     LOGI << QString("(%1/%2) attempts").arg(attempts).arg(MAX_ATTEMPTS) << ", preform portal prelogin at " << preloginUrl; | ||||
|     LOGI << QString("(%1/%2) attempts").arg(attempts).arg(MAX_ATTEMPTS) << ", perform portal prelogin at " << preloginUrl; | ||||
|  | ||||
|     QNetworkReply *reply = createRequest(preloginUrl); | ||||
|     connect(reply, &QNetworkReply::finished, this, &PortalAuthenticator::onPreloginFinished); | ||||
| @@ -118,7 +118,7 @@ void PortalAuthenticator::samlAuth() | ||||
| { | ||||
|     LOGI << "Trying to perform SAML login with saml-method " << preloginResponse.samlMethod(); | ||||
|  | ||||
|     auto *loginWindow = new SAMLLoginWindow; | ||||
|     auto *loginWindow = new SAMLLoginWindow(this->portal); | ||||
|  | ||||
|     connect(loginWindow, &SAMLLoginWindow::success, [this, loginWindow](const QMap<QString, QString> samlResult) { | ||||
|         this->onSAMLLoginSuccess(samlResult); | ||||
|   | ||||
| @@ -172,4 +172,3 @@ void PortalConfigResponse::setPrelogonUserAuthCookie(const QString cookie) | ||||
| { | ||||
|     m_prelogonAuthCookie = cookie; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -4,9 +4,10 @@ | ||||
| #include <QWebEngineCookieStore> | ||||
| #include <plog/Log.h> | ||||
|  | ||||
| #include "INIReader.h" | ||||
| #include "samlloginwindow.h" | ||||
|  | ||||
| SAMLLoginWindow::SAMLLoginWindow(QWidget *parent) | ||||
| SAMLLoginWindow::SAMLLoginWindow(QString portal, QWidget *parent) | ||||
|     : QDialog(parent) | ||||
|     , webView(new EnhancedWebView(this)) | ||||
| { | ||||
| @@ -23,6 +24,9 @@ SAMLLoginWindow::SAMLLoginWindow(QWidget *parent) | ||||
|     connect(webView, &EnhancedWebView::responseReceived, this, &SAMLLoginWindow::onResponseReceived); | ||||
|     connect(webView, &EnhancedWebView::loadFinished, this, &SAMLLoginWindow::onLoadFinished); | ||||
|  | ||||
|     // Portal | ||||
|     this->portal = portal; | ||||
|  | ||||
|     // Show the login window automatically when exceeds the MAX_WAIT_TIME | ||||
|     QTimer::singleShot(MAX_WAIT_TIME, this, [this]() { | ||||
|         if (failed) { | ||||
| @@ -108,6 +112,9 @@ void SAMLLoginWindow::onLoadFinished() | ||||
| { | ||||
|      LOGI << "Load finished " << webView->page()->url().toString(); | ||||
|      webView->page()->toHtml([this] (const QString &html) { this->handleHtml(html); }); | ||||
|      QMap<QString, QString> credentials = this->loadCredentials(); | ||||
|      webView->page()->runJavaScript("document.getElementById('username').value='" + credentials["username"] + "';"); | ||||
|      webView->page()->runJavaScript("document.getElementById('password').value='" + credentials["password"] + "';"); | ||||
| } | ||||
|  | ||||
| void SAMLLoginWindow::handleHtml(const QString &html) | ||||
| @@ -134,3 +141,25 @@ QString SAMLLoginWindow::parseTag(const QString &tag, const QString &html) { | ||||
|     const QRegularExpression expression(QString("<%1>(.*)</%1>").arg(tag)); | ||||
|     return expression.match(html).captured(1); | ||||
| } | ||||
|  | ||||
| QMap<QString, QString> SAMLLoginWindow::loadCredentials() | ||||
| { | ||||
|     std::string home = getenv("HOME"); | ||||
|     std::string iniFile = home + "/.gpclient-credentials"; | ||||
|     INIReader reader(iniFile); | ||||
|  | ||||
|     QMap<QString, QString> credentials; | ||||
|     if (reader.ParseError() < 0) { | ||||
|         LOGE << "File '" << iniFile << "' not found."; | ||||
|         return credentials; | ||||
|     } | ||||
|  | ||||
|     if (reader.HasSection(this->portal.toStdString())) { | ||||
|         credentials.insert(QString("username"), QString::fromStdString(reader.Get(this->portal.toStdString(), "username", ""))); | ||||
|         credentials.insert(QString("password"), QString::fromStdString(reader.Get(this->portal.toStdString(), "password", ""))); | ||||
|     } else { | ||||
|         LOGE << "No credentials found for '" << this->portal.toStdString() << "' in '" << iniFile << "'"; | ||||
|     } | ||||
|  | ||||
|     return credentials; | ||||
| } | ||||
| @@ -12,9 +12,10 @@ class SAMLLoginWindow : public QDialog | ||||
|     Q_OBJECT | ||||
|  | ||||
| public: | ||||
|     explicit SAMLLoginWindow(QWidget *parent = nullptr); | ||||
|     explicit SAMLLoginWindow(QString portal, QWidget *parent = nullptr); | ||||
|  | ||||
|     void login(const QString samlMethod, const QString samlRequest, const QString preloginUrl); | ||||
|     QMap<QString, QString> loadCredentials(); | ||||
|  | ||||
| signals: | ||||
|     void success(QMap<QString, QString> samlResult); | ||||
| @@ -31,6 +32,7 @@ private: | ||||
|     bool failed { false }; | ||||
|     EnhancedWebView *webView { nullptr }; | ||||
|     QMap<QString, QString> samlResult; | ||||
|     QString portal; | ||||
|  | ||||
|     void closeEvent(QCloseEvent *event); | ||||
|     void handleHtml(const QString &html); | ||||
|   | ||||
| @@ -32,3 +32,11 @@ QString SettingsDialog::clientos() | ||||
| { | ||||
|     return ui->clientosInput->text(); | ||||
| } | ||||
|  | ||||
| void SettingsDialog::setOsVersion(QString osVersion) { | ||||
|     ui->osVersionInput->setText(osVersion); | ||||
| } | ||||
|  | ||||
| QString SettingsDialog::osVersion() { | ||||
|     return ui->osVersionInput->text(); | ||||
| } | ||||
|   | ||||
| @@ -21,6 +21,9 @@ public: | ||||
|     void setClientos(QString clientos); | ||||
|     QString clientos(); | ||||
|  | ||||
|     void setOsVersion(QString osVersion); | ||||
|     QString osVersion(); | ||||
|  | ||||
| private: | ||||
|     Ui::SettingsDialog *ui; | ||||
| }; | ||||
|   | ||||
| @@ -7,7 +7,7 @@ | ||||
|     <x>0</x> | ||||
|     <y>0</y> | ||||
|     <width>488</width> | ||||
|     <height>177</height> | ||||
|     <height>220</height> | ||||
|    </rect> | ||||
|   </property> | ||||
|   <property name="sizePolicy"> | ||||
| @@ -44,7 +44,7 @@ | ||||
|    <item row="1" column="0"> | ||||
|     <widget class="QLabel" name="label_2"> | ||||
|      <property name="text"> | ||||
|       <string>Value of "clientos":</string> | ||||
|       <string>clientos:</string> | ||||
|      </property> | ||||
|     </widget> | ||||
|    </item> | ||||
| @@ -55,7 +55,7 @@ | ||||
|      </property> | ||||
|     </widget> | ||||
|    </item> | ||||
|    <item row="2" column="1"> | ||||
|    <item row="3" column="1"> | ||||
|     <widget class="QDialogButtonBox" name="buttonBox"> | ||||
|      <property name="orientation"> | ||||
|       <enum>Qt::Horizontal</enum> | ||||
| @@ -65,6 +65,16 @@ | ||||
|      </property> | ||||
|     </widget> | ||||
|    </item> | ||||
|    <item row="2" column="1"> | ||||
|     <widget class="QLineEdit" name="osVersionInput"/> | ||||
|    </item> | ||||
|    <item row="2" column="0"> | ||||
|     <widget class="QLabel" name="label_3"> | ||||
|      <property name="text"> | ||||
|       <string>os-version:</string> | ||||
|      </property> | ||||
|     </widget> | ||||
|    </item> | ||||
|   </layout> | ||||
|  </widget> | ||||
|  <resources> | ||||
|   | ||||
| @@ -2,6 +2,9 @@ | ||||
|  | ||||
| #include "standardloginwindow.h" | ||||
| #include "ui_standardloginwindow.h" | ||||
| #include "gphelper.h" | ||||
|  | ||||
| using namespace gpclient::helper; | ||||
|  | ||||
| StandardLoginWindow::StandardLoginWindow(const QString &portalAddress, const QString &labelUsername, | ||||
|                                          const QString &labelPassword, const QString &authMessage) : | ||||
| @@ -13,11 +16,24 @@ StandardLoginWindow::StandardLoginWindow(const QString &portalAddress, const QSt | ||||
|     ui->password->setPlaceholderText(labelPassword); | ||||
|     ui->authMessage->setText(authMessage); | ||||
|  | ||||
|     autocomplete(); | ||||
|  | ||||
|     setWindowTitle("GlobalProtect Login"); | ||||
|     setFixedSize(width(), height()); | ||||
|     setModal(true); | ||||
| } | ||||
|  | ||||
| void StandardLoginWindow::autocomplete() { | ||||
|     QString username, password; | ||||
|     settings::secureGet("username", username); | ||||
|     settings::secureGet("password", password); | ||||
|  | ||||
|     if (!username.isEmpty() && !password.isEmpty()) { | ||||
|         ui->username->setText(username); | ||||
|         ui->password->setText(password); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void StandardLoginWindow::setProcessing(bool isProcessing) { | ||||
|     ui->username->setReadOnly(isProcessing); | ||||
|     ui->password->setReadOnly(isProcessing); | ||||
| @@ -32,6 +48,9 @@ void StandardLoginWindow::on_loginButton_clicked() { | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     settings::secureSave("username", username); | ||||
|     settings::secureSave("password", password); | ||||
|  | ||||
|     emit performLogin(username, password); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -28,6 +28,7 @@ private: | ||||
|     Ui::StandardLoginWindow *ui; | ||||
|  | ||||
|     void closeEvent(QCloseEvent *event); | ||||
|     void autocomplete(); | ||||
| }; | ||||
|  | ||||
| #endif // STANDARDLOGINWINDOW_H | ||||
|   | ||||
| @@ -34,9 +34,9 @@ GPService::~GPService() | ||||
|  | ||||
| QString GPService::findBinary() | ||||
| { | ||||
|     for (int i = 0; i < binaryPaths->length(); i++) { | ||||
|         if (QFileInfo::exists(binaryPaths[i])) { | ||||
|             return binaryPaths[i]; | ||||
|     for (auto& binaryPath : binaryPaths) { | ||||
|         if (QFileInfo::exists(binaryPath)) { | ||||
|             return binaryPath; | ||||
|         } | ||||
|     } | ||||
|     return nullptr; | ||||
| @@ -136,7 +136,7 @@ void GPService::connect(QString server, QString username, QString passwd) | ||||
|          << "--cookie-on-stdin" | ||||
|          << server; | ||||
|  | ||||
|     log("Start process with arugments: " + args.join(", ")); | ||||
|     log("Start process with arguments: " + args.join(", ")); | ||||
|  | ||||
|     openconnect->start(bin, args); | ||||
|     openconnect->write((passwd + "\n").toUtf8()); | ||||
| @@ -199,7 +199,9 @@ void GPService::onProcessStdout() | ||||
|     QString output = openconnect->readAllStandardOutput(); | ||||
|  | ||||
|     log(output); | ||||
|     if (output.indexOf("Connected as") >= 0 || output.indexOf("Configured as") >= 0) { | ||||
|     if (output.indexOf("Connected as") >= 0 || | ||||
|         output.indexOf("Configured as") >= 0 || | ||||
|         output.indexOf("Configurado como") >= 0) { | ||||
|         vpnStatus = GPService::VpnConnected; | ||||
|         emit connected(); | ||||
|     } | ||||
|   | ||||
| @@ -4,14 +4,13 @@ | ||||
| #include <QtCore/QObject> | ||||
| #include <QtCore/QProcess> | ||||
|  | ||||
| static const QString binaryPaths[] { | ||||
|     "/usr/local/bin/openconnect", | ||||
|     "/usr/local/sbin/openconnect", | ||||
|     "/usr/bin/openconnect", | ||||
|     "/usr/sbin/openconnect", | ||||
|     "/opt/bin/openconnect", | ||||
|     "/opt/sbin/openconnect" | ||||
| }; | ||||
| static QList<QString> binaryPaths = QList<QString>() << | ||||
|     "/usr/local/bin/openconnect" << | ||||
|      "/usr/local/sbin/openconnect" << | ||||
|      "/usr/bin/openconnect" << | ||||
|      "/usr/sbin/openconnect" << | ||||
|      "/opt/bin/openconnect" << | ||||
|      "/opt/sbin/openconnect"; | ||||
|  | ||||
| class GPService : public QObject | ||||
| { | ||||
|   | ||||
							
								
								
									
										12
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								README.md
									
									
									
									
									
								
							| @@ -78,7 +78,8 @@ sudo dnf install globalprotect-openconnect | ||||
| - openSUSE Leap | ||||
|  | ||||
|   ```sh   | ||||
|   sudo zypper ar https://download.opensuse.org/repositories/home:/yuezk/openSUSE_Leap_15.2/home:yuezk.repo | ||||
|   sudo zypper ar https://download.opensuse.org/repositories/home:/yuezk/15.4/home:yuezk.repo | ||||
|    | ||||
|   sudo zypper ref | ||||
|   sudo zypper install globalprotect-openconnect | ||||
|   ``` | ||||
| @@ -97,6 +98,14 @@ git clone https://github.com/yuezk/GlobalProtect-openconnect.git | ||||
| cd GlobalProtect-openconnect | ||||
| ``` | ||||
|  | ||||
| ### MX Linux | ||||
| The following instructions are for **MX-21.2.1_x64 KDE**. | ||||
|  | ||||
| ```sh | ||||
| sudo apt install qttools5-dev libsecret-1-dev libqt5keychain1 | ||||
| ./scripts/install-debian.sh | ||||
| ``` | ||||
|  | ||||
| ### Ubuntu/Mint | ||||
|  | ||||
| > **⚠️ REQUIRED for Ubuntu 18.04 ⚠️** | ||||
| @@ -138,6 +147,7 @@ Install the Qt5 dependencies and OpenConnect: | ||||
| - QtWebSockets | ||||
| - QtDBus | ||||
| - openconnect v8.x | ||||
| - qtkeychain | ||||
|  | ||||
| ...then build and install with: | ||||
|  | ||||
|   | ||||
							
								
								
									
										2
									
								
								cmakew
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								cmakew
									
									
									
									
									
								
							| @@ -36,7 +36,7 @@ fi | ||||
| cmake_base="./.cmake" | ||||
| cmake_bin="${cmake_base}/cmake-$cmake_version/bin/cmake" | ||||
|  | ||||
| # download cmake if neccessary | ||||
| # download cmake if necessary | ||||
| if [ ! -f "$cmake_bin" ]; then | ||||
|     download_link="" | ||||
|  | ||||
|   | ||||
							
								
								
									
										35
									
								
								debian/changelog
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										35
									
								
								debian/changelog
									
									
									
									
										vendored
									
									
								
							| @@ -1,3 +1,34 @@ | ||||
| globalprotect-openconnect (1.4.9-1) unstable; urgency=medium | ||||
|  | ||||
|   * Updated VERSION, Bumped 1.4.8 –> 1.4.9 | ||||
|   * fix: update cmake version | ||||
|   * fix: correct the package name | ||||
|   * fix: use the dev package | ||||
|   * fix: use qtkeychain package | ||||
|   * fix: add qt5-tools | ||||
|   * fix: add libsecret-1-dev | ||||
|   * fix: add pkg-config | ||||
|   * fix: use cmake 3.16 | ||||
|   * fix: add missing build dependency | ||||
|   * ci: fix CI | ||||
|   * Merge branch 'master' into develop | ||||
|   * feat: expose os-version to settings | ||||
|   * Add two missing dependencies for building on debian (#198) | ||||
|   * ci: assert no library missing | ||||
|   * fix: update qtkeychain | ||||
|   * ci: run gpclient after build | ||||
|   * fix: add qtkeychain | ||||
|   * chore: update CMake file | ||||
|   * Added install instructions for MX Linux. (#190) | ||||
|   * Credentials autocompleting (secure version) (#179) | ||||
|   * Read all saved Gateways (for selecting in Systray) (#181) | ||||
|   * copy install script for debian (#180) | ||||
|   * add es and pt support to shange status when connected to vpn (#162) | ||||
|   * fix: improve the cli support | ||||
|   * feat: add --reset option to gpclient | ||||
|  | ||||
|  -- Kevin Yue <k3vinyue@gmail.com>  Sun, 08 Jan 2023 20:58:32 +0800 | ||||
|  | ||||
| globalprotect-openconnect (1.4.8-1) unstable; urgency=medium | ||||
|  | ||||
|   * Updated VERSION, Bumped 1.4.7 –> 1.4.8 | ||||
| @@ -26,7 +57,7 @@ globalprotect-openconnect (1.4.6-1) unstable; urgency=medium | ||||
|  | ||||
|   * Updated VERSION, Bumped 1.4.5 –> 1.4.6 | ||||
|   * feat: display address in gateway menu item | ||||
|   * fix: fix bug of parsing the portal respponse | ||||
|   * fix: fix bug of parsing the portal response | ||||
|  | ||||
|  -- Kevin Yue <k3vinyue@gmail.com>  Wed, 01 Jun 2022 23:55:50 +0800 | ||||
|  | ||||
| @@ -39,7 +70,7 @@ globalprotect-openconnect (1.4.5-1) unstable; urgency=medium | ||||
|   * packaging: fix postinst for debian | ||||
|   * packaging: add postinst for debian | ||||
|   * test: test debian packaging | ||||
|   * ci: fix the foder path | ||||
|   * ci: fix the folder path | ||||
|   * chore: apt -> apt-get | ||||
|   * ci: verify debian package | ||||
|   * Revert "Revert "fix: improve the dbus security"" | ||||
|   | ||||
							
								
								
									
										4
									
								
								debian/control
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								debian/control
									
									
									
									
										vendored
									
									
								
							| @@ -2,12 +2,12 @@ Source: globalprotect-openconnect | ||||
| Section: net | ||||
| Priority: optional | ||||
| Maintainer: Kevin Yue <k3vinyue@gmail.com> | ||||
| Build-Depends: cmake (>=3.10), debhelper (>=11~), qtbase5-dev, libqt5websockets5-dev (>=5.9), qtwebengine5-dev (>=5.9) | ||||
| Build-Depends: cmake (>=3.10), pkg-config, debhelper (>=11~), qtbase5-dev, qttools5-dev, libqt5websockets5-dev (>=5.9), qtwebengine5-dev (>=5.9), qt5keychain-dev | ||||
| Standards-Version: 4.1.4 | ||||
| Homepage: https://github.com/yuezk/GlobalProtect-openconnect | ||||
|  | ||||
| Package: globalprotect-openconnect | ||||
| Architecture: any | ||||
| Multi-Arch: foreign | ||||
| Depends: ${misc:Depends}, ${shlibs:Depends}, openconnect (>=8.0), libqt5websockets5 (>=5.9), libqt5webengine5 (>=5.9) | ||||
| Depends: ${misc:Depends}, ${shlibs:Depends}, openconnect (>=8.0), libqt5websockets5 (>=5.9), libqt5webengine5 (>=5.9), libqt5keychain1 | ||||
| Description: A GlobalProtect VPN client (GUI) based on OpenConnect. | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| # Maintainer: Keinv Yue <yuezk001@gmail.com> | ||||
|  | ||||
| _pkgver="1.4.8" | ||||
| _commit="3559834762c1e450887e40c70ed6f775f5421903" | ||||
| _pkgver="1.4.9" | ||||
| _commit="acf184134a2ff19e4a39528bd6a7fbbafa4cf017" | ||||
| pkgname=globalprotect-openconnect-git | ||||
| pkgver=${_pkgver} | ||||
| pkgrel=1 | ||||
| @@ -13,7 +13,7 @@ backup=( | ||||
|     etc/gpservice/gp.conf | ||||
| ) | ||||
| install=gp.install | ||||
| depends=('openconnect>=8.0.0' qt5-base qt5-webengine qt5-websockets) | ||||
| depends=('openconnect>=8.0.0' qt5-base qt5-webengine qt5-websockets qt5-tools qtkeychain-qt5) | ||||
| makedepends=(git cmake) | ||||
| conflicts=('globalprotect-openconnect') | ||||
| provides=('globalprotect-openconnect' 'gpclient' 'gpservice') | ||||
|   | ||||
| @@ -13,7 +13,7 @@ backup=( | ||||
|     etc/gpservice/gp.conf | ||||
| ) | ||||
| install=gp.install | ||||
| depends=('openconnect>=8.0.0' qt5-base qt5-webengine qt5-websockets) | ||||
| depends=('openconnect>=8.0.0' qt5-base qt5-webengine qt5-websockets qt5-tools qtkeychain-qt5) | ||||
| makedepends=(git cmake) | ||||
| conflicts=('globalprotect-openconnect') | ||||
| provides=('globalprotect-openconnect' 'gpclient' 'gpservice') | ||||
|   | ||||
| @@ -1,3 +1,34 @@ | ||||
| ------------------------------------------------------------------- | ||||
| Sun Jan  8 12:58:32 UTC 2023 - k3vinyue@gmail.com - 1.4.9 | ||||
|  | ||||
| - Update to 1.4.9 | ||||
|   * Updated VERSION, Bumped 1.4.8 –> 1.4.9 | ||||
|   * fix: update cmake version | ||||
|   * fix: correct the package name | ||||
|   * fix: use the dev package | ||||
|   * fix: use qtkeychain package | ||||
|   * fix: add qt5-tools | ||||
|   * fix: add libsecret-1-dev | ||||
|   * fix: add pkg-config | ||||
|   * fix: use cmake 3.16 | ||||
|   * fix: add missing build dependency | ||||
|   * ci: fix CI | ||||
|   * Merge branch 'master' into develop | ||||
|   * feat: expose os-version to settings | ||||
|   * Add two missing dependencies for building on debian (#198) | ||||
|   * ci: assert no library missing | ||||
|   * fix: update qtkeychain | ||||
|   * ci: run gpclient after build | ||||
|   * fix: add qtkeychain | ||||
|   * chore: update CMake file | ||||
|   * Added install instructions for MX Linux. (#190) | ||||
|   * Credentials autocompleting (secure version) (#179) | ||||
|   * Read all saved Gateways (for selecting in Systray) (#181) | ||||
|   * copy install script for debian (#180) | ||||
|   * add es and pt support to change status when connected to vpn (#162) | ||||
|   * fix: improve the cli support | ||||
|   * feat: add --reset option to gpclient | ||||
|  | ||||
| ------------------------------------------------------------------- | ||||
| Sun Jun 12 12:28:58 UTC 2022 - k3vinyue@gmail.com - 1.4.8 | ||||
|  | ||||
| @@ -28,7 +59,7 @@ Wed Jun  1 15:55:50 UTC 2022 - k3vinyue@gmail.com - 1.4.6 | ||||
| - Update to 1.4.6 | ||||
|   * Updated VERSION, Bumped 1.4.5 –> 1.4.6 | ||||
|   * feat: display address in gateway menu item | ||||
|   * fix: fix bug of parsing the portal respponse | ||||
|   * fix: fix bug of parsing the portal response | ||||
|  | ||||
| ------------------------------------------------------------------- | ||||
| Sun May 29 13:15:40 UTC 2022 - k3vinyue@gmail.com - 1.4.5 | ||||
| @@ -41,7 +72,7 @@ Sun May 29 13:15:40 UTC 2022 - k3vinyue@gmail.com - 1.4.5 | ||||
|   * packaging: fix postinst for debian | ||||
|   * packaging: add postinst for debian | ||||
|   * test: test debian packaging | ||||
|   * ci: fix the foder path | ||||
|   * ci: fix the folder path | ||||
|   * chore: apt -> apt-get | ||||
|   * ci: verify debian package | ||||
|   * Revert "Revert "fix: improve the dbus security"" | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| Name:           globalprotect-openconnect | ||||
| Version:        1.4.8 | ||||
| Version:        1.4.9 | ||||
| Release:        1 | ||||
| Summary:        A GlobalProtect VPN client powered by OpenConnect | ||||
| Group:          Productivity/Networking/PPP | ||||
| @@ -8,7 +8,7 @@ BuildRoot:      %{_tmppath}/%{name}-%{version}-build | ||||
| License:        GPL-3.0 | ||||
| URL:            https://github.com/yuezk/GlobalProtect-openconnect | ||||
| Source0:        %{name}.tar.gz | ||||
| BuildRequires:  cmake cmake(Qt5) cmake(Qt5Gui) cmake(Qt5WebEngine) cmake(Qt5WebSockets) cmake(Qt5DBus) | ||||
| BuildRequires:  cmake cmake(Qt5) cmake(Qt5Gui) cmake(Qt5WebEngine) cmake(Qt5WebSockets) cmake(Qt5DBus) cmake(Qt5Keychain) | ||||
| BuildRequires:  systemd-rpm-macros | ||||
| Requires:       openconnect >= 8.0 | ||||
| Conflicts:      globalprotect-openconnect-snapshot | ||||
|   | ||||
							
								
								
									
										13
									
								
								scripts/install-debian.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										13
									
								
								scripts/install-debian.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| #!/bin/bash -e | ||||
|  | ||||
| sudo apt-get update | ||||
| sudo apt-get install -y \ | ||||
|     build-essential \ | ||||
|     qtbase5-dev \ | ||||
|     libqt5websockets5-dev \ | ||||
|     qtwebengine5-dev \ | ||||
|     qttools5-dev \ | ||||
|     qt5keychain-dev \ | ||||
|     openconnect \ | ||||
|  | ||||
| ./scripts/install.sh | ||||
| @@ -4,6 +4,7 @@ sudo dnf install -y \ | ||||
|     qt5-qtbase-devel \ | ||||
|     qt5-qtwebengine-devel \ | ||||
|     qt5-qtwebsockets-devel \ | ||||
|     qtkeychain-qt5-devel \ | ||||
|     openconnect | ||||
|  | ||||
| ./scripts/install.sh | ||||
| @@ -4,6 +4,7 @@ sudo zypper install -y \ | ||||
|     libqt5-qtbase-devel \ | ||||
|     libqt5-qtwebsockets-devel \ | ||||
|     libqt5-qtwebengine-devel \ | ||||
|     qtkeychain-qt5-devel \ | ||||
|     openconnect | ||||
|  | ||||
| ./scripts/install.sh | ||||
| @@ -6,6 +6,8 @@ sudo apt-get install -y \ | ||||
|     qtbase5-dev \ | ||||
|     libqt5websockets5-dev \ | ||||
|     qtwebengine5-dev \ | ||||
|     qttools5-dev \ | ||||
|     qt5keychain-dev \ | ||||
|     openconnect | ||||
|  | ||||
| ./scripts/install.sh | ||||
|   | ||||
| @@ -6,7 +6,9 @@ sudo apt-get install -y \ | ||||
| 	qtbase5-dev \ | ||||
| 	libqt5websockets5-dev \ | ||||
| 	qtwebengine5-dev \ | ||||
| 	qt5keychain-dev \ | ||||
| 	cmake \ | ||||
| 	qttools5-dev \ | ||||
| 	debhelper | ||||
|  | ||||
| mkdir -p build | ||||
|   | ||||
		Reference in New Issue
	
	Block a user